1

我正在研究 Postgres 8.3 数据库,并试图使用 PL/pgSQL 创建函数,该函数根据输入到表的日期生成表名:

我必须创建一系列按日期索引的表,例如:

drop table one_day_11_13 cascade;
create table one_day_11_13 as
select * from master_table where
timestamp < '2012-11-14' and timestamp >= '2012-11-13';  

drop table one_day_11_14 cascade;
create table one_day_11_14 as
select * from master_table where
timestamp < '2012-11-15' and timestamp >= '2012-11-14';  

我在想这样做的方法是创建一个 PL/pgSQL 函数,该函数将作为参数('11_13', '2012-11-14', '2012-11-13'),例如创建上面的第一个表。我在编写适当的 EXECUTE 语句时遇到问题。

做这种事情的最好方法是 PL/pgSQL 矫枉过正吗?

4

1 回答 1

4

首先,考虑升级到更新的版本。8.3 即将推出。

对于 8.3,它可以像这样工作:

CREATE OR REPLACE FUNCTION f_recreate_tbl(date, date)
 RETURNS void AS
$func$
DECLARE
   -- derive tablename from first date
   _tbl text := 'one_day_' || to_char($1, 'MM_YY'); 
BEGIN

 -- Use IF EXISTS to avoid an exception when table does not exist.
EXECUTE
'DROP TABLE IF EXISTS ' || _tbl || ' CASCADE';

EXECUTE 
'CREATE TABLE ' || _tbl || ' AS
SELECT *
FROM   master_table
WHERE  timestamp >= ''' || $1::text || '''::date
AND    timestamp <  ''' || $2::text || '''::date';

END
$func$ LANGUAGE plpgsql;

称呼:

SELECT f_recreate_tbl('2012-11-13'::date, '2012-11-14'::date);
  • 每当您想参数化标识符时,您都不能使用纯 SQL。EXECUTE在 PL/pgSQL 函数或DO语句中使用动态 SQL (版本 9.0+)。

  • 这个版本足够安全。使用更灵活的输入,您必须使用quote_ident()quote_literal()防止可能的 SQL 注入来清理标识符和值。

  • 在现代版本(自 8.4 起)中,您将使用该USING子句跳过将参数转换为文本。

  • 不要timestamp用作列名。它是数据类型的名称。

  • 使用DROP TABLE IF EXISTS. 已经在 8.3 中可用。

  • 我从日期派生表名并跳过第三个参数。似乎是一种简化。

于 2012-12-10T19:39:42.940 回答