sql - 参数化表名

标签 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 矫枉过正?

最佳答案

首先,考虑升级到更新的版本。 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。使用 EXECUTE PL/pgSQL 函数中的动态 SQL 或 DO statement (版本 9.0+)。

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

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

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

  • 使用DROP TABLE IF EXISTSAlready available in 8.3.

  • 我从日期派生表名并跳过第三个参数。看起来像是一种简化。

关于sql - 参数化表名,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13805714/

相关文章:

sql - 将 varchar 转换为日期

sql - 围绕单个语句的事务有什么作用?

php - 如何从 html/php 页面内的 mySQL 数据库打印表格

ruby-on-rails - 在一个月内创建的 Rails 范围

ruby-on-rails - 在 jsonb postgres 中按日期排序

function - 在 postgresql 中运行函数抛出运行时错误

arrays - 带有文本数组的Postgres函数并选择查询位置

php 计数 vs sql 计数 vs 计数字段?演出

linux - 使用 ansible 应用数据库迁移

postgresql - 将主键添加到数据库中还没有主键的所有表