在动态SQL之前截断表,在一个函数内部使用循环变量

时间:2013-08-06 20:18:58

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

我有一个循环遍历特定模式名称并将数据插入表中的函数。我希望能够在插入循环发生之前截断所述表。我已经尝试将truncate语句放在动态查询中,这导致它只将schema的数据保存在表中。我也尝试将它声明为它自己的变量,然后与循环语句分开执行语句 - 但结果相同。

所以我的问题是 - 我究竟会在这个函数中放置一个truncate table dwh.prod_table_notify语句?因此,每次运行此函数时,表都将被截断,然后插入将正确循环遍历从FOR语句返回的每个模式。

注意:我被迫使用postgres 8.2

CREATE OR REPLACE FUNCTION dwh.dim_table_notification()
 RETURNS void
 LANGUAGE plpgsql
AS $function$
Declare
       myschema varchar;
       sql2 text;                   
Begin 
for myschema in 
select distinct table_schema
from information_schema.tables
where table_name in ('dim_loan_type', 'dim_acct_type')
and table_schema NOT LIKE 'pg_%'
and table_schema NOT IN ('information_schema', 'ad_delivery', 'dwh', 'users', 'wand', 'ttd') 
order by table_schema
loop  
sql2 ='insert into dwh.prod_table_notify 
select '''|| myschema ||''' as userid, loan_type_id as acct_type_id, loan_type::varchar(10) as acct_type, loan_type_desc::varchar(50) as acct_type_desc, term_code, 1 as loan_type from '|| myschema || '.' ||'dim_loan_type where term_code is null
union
select '''|| myschema ||''' as userid, acct_type_id, acct_type::varchar(10), acct_type_desc::varchar(50), term_code, 0 as loan_type from '|| myschema || '.' ||'dim_acct_type where term_code is null';
execute sql2;
end loop;
END;
$function$

1 个答案:

答案 0 :(得分:1)

CREATE OR REPLACE FUNCTION dwh.dim_table_notification()
  RETURNS void LANGUAGE plpgsql AS
$func$
DECLARE
   myschema text;
BEGIN

-- truncate simply goes here:
TRUNCATE dwh.prod_table_notify;

FOR myschema IN
   SELECT quote_ident(table_schema)
   FROM   information_schema.tables
   WHERE  table_name IN ('dim_loan_type', 'dim_acct_type')
   AND    table_schema NOT LIKE 'pg_%'
   AND    table_schema NOT IN
          ('information_schema', 'ad_delivery', 'dwh', 'users', 'wand', 'ttd')
   ORDER  BY table_schema
LOOP
   EXECUTE '
   INSERT INTO dwh.prod_table_notify
              (userid, acct_type_id, acct_type, acct_type_desc, loan_type)
   SELECT '''|| myschema ||''', loan_type_id, loan_type::varchar(10)
        , loan_type_desc::varchar(50), term_code, 1 AS loan_type
   FROM   '|| myschema || '.dim_loan_type
   WHERE  term_code IS NULL
   UNION ALL
   SELECT '''|| myschema ||''' AS userid, acct_type_id, acct_type::varchar(10)
       , acct_type_desc::varchar(50), term_code, 0 AS loan_type
   FROM   '|| myschema || '.dim_acct_type
   WHERE term_code IS NULL';
END LOOP;
END
$func$
  • 您确定可以使用TRUNCATE吗?引用the manual for 8.2

      

    TRUNCATE不能用于具有其他表的外键引用的表,除非所有这些表也在同一命令中被截断。

    如果表DELETE的开头速度比TRUNCATE快: DELETE FROM dwh.prod_table_notify;

  • 您必须清理标识符!使用quote_ident(),也可在第8.2页中找到。

  • 此处使用DISTINCT毫无意义。

  • INSERT提供列定义列表。此外,当您稍后更改表格时,它可能会以混乱的方式打破。

  • 如果SELECT的两条腿中的行是唯一的,请使用UNION ALL代替UNION。尝试折叠副本没有意义。