从另一个表中的表名列表中填充临时表

时间:2014-07-21 14:35:48

标签: sql postgresql plpgsql dynamic-sql union-all

我一直在寻找其他线程上的解决方案,但是我从其他主题中得到的只是我需要的一些部分,我无法将它们绑在一起才能正常工作。

问题的背景是:每天晚上将事务日志写入数据库中新创建的表,然后清除主日志。创建的表的名称与日期无关(难以搜索历史日志 - 因此无法猜测给定日期的表名或硬编码)。

但是,一旦将事务移动到新表中,日志记录表就会添加一条新记录,用于存储日期和有关已归档记录的其他信息(包括表的名称)。

我正在尝试编写一个允许我将日期范围(开始日期和结束日期)传递给它的函数,然后返回在给定日期范围内具有信息的所有表的名称 - 将名称存储在阵列。填充数组后,将对阵列中的每个表运行SQL查询,以将所有这些写入单个临时表,从而允许对其进行查询。

一些伪代码将是:

CREATE OR REPLACE FUNCTION transactions(begin_date varchar(10), end_date varchar(10)) RETURN void as $$
Begin
SELECT INTO table_names 'name' from 'log_table' where 'log_date' between begin_date and end_date;
FOREACH table_names LOOP
SQL_Query = "INSERT INTO temporary_table SELECT * from " + table_names;
EXECUTE SQL_Query;
END LOOP;

任何帮助都表示赞赏 - 我的逻辑可以完全打破,我需要改变我的方法。

1 个答案:

答案 0 :(得分:0)

CREATE OR REPLACE FUNCTION f_create_temp_trans(_begin date
                                              ,_end   date, OUT _rows int) AS
$func$
BEGIN

DROP TABLE IF EXISTS temp_trans;
CREATE TEMP TABLE IF NOT EXISTS temp_trans (LIKE existing_tbl);

EXECUTE (
   SELECT E'INSERT INTO temp_trans\NSELECT * FROM '
       || string_agg(quote_ident(tbl_name)
                   , E'\NUNION ALL SELECT * FROM '
                     ORDER  BY log_date)
   FROM   log_table
   WHERE  log_date BETWEEN _begin AND _end
   );

GET DIAGNOSTICS _rows = ROW_COUNT;

END
$func$ LANGUAGE plpgsql;

呼叫:

SELECT * FROM f_create_temp_trans('2014-06-01', '2014-06-11');

返回插入临时表的行数。

重点

  • 创建名为temp_trans的临时表(抢占式)(在会话期间有效)。结构从existing_tbl复制 - 替换为实际的表名。

  • 使用汇总函数string_agg()INSERT 组成UNION ALL,这比运行许多INSERT更有效语句。

  • 生成并执行以下形式的声明:

    INSERT INTO temp_trans
    SELECT * FROM tbl1
    UNION ALL SELECT * FROM "trickY name tbl2"
    UNION ALL SELECT * FROM tbl3
    ...
    
  • 单引号('val')用于值,而不是标识符,必要时使用双引号。

  • 为什么您的约会varchar(10)?在我的代码中使用 date 就好了。

  • 关于GET DIAGNOSTICS

  • E'\N'是换行符。只是为了调试生成的SQL代码以进行调试。不需要。你可以用空格替换:

    ...
    SELECT 'INSERT INTO temp_trans SELECT * FROM '
        || string_agg(quote_ident(tbl_name), ' UNION ALL SELECT * FROM ' ...
    

    关于引用和转义字符串: