参数化表名

时间:2012-12-10 17:11:34

标签: sql postgresql plpgsql dynamic-sql postgresql-8.3

我正在使用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过度杀伤?

1 个答案:

答案 0 :(得分:4)

首先,考虑升级到更新版本。 8.3 is on its way out.

对于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。在PL / pgSQL函数或EXECUTE(版本9.0 +)中使用DO statement动态SQL。

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

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

  • 请勿使用timestamp作为列名。它是数据类型的名称。

  • 使用DROP TABLE IF EXISTS Already available in 8.3.

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