Question

I have a function that loops through specific schema names and inserts data into a table. I would like to be able to truncate said table before the insert loop occurs. I've tried putting the truncate statement inside of the dynamic query and that caused it to only keep schema's data inside of the table. I also tried declaring it as it's own variable and then executing the statement separately from the looping statement -- but that resulted in the same.

So my question is -- Where exactly would I put a truncate table dwh.prod_table_notify statement within this function? So that every time I run this function the table would be truncated and then the insert would properly loop through each schema being returned from the FOR statement.

NOTE: I'm forced to use 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$
Was it helpful?

Solution

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$
  • Are you sure, you can actually use TRUNCATE? Quoting the manual for 8.2:

    TRUNCATE cannot be used on a table that has foreign-key references from other tables, unless all such tables are also truncated in the same command.

    If tables are small, DELETE is faster than TRUNCATE to begin with:
    DELETE FROM dwh.prod_table_notify;

  • You have to sanitize identifiers! Use quote_ident(), also available in pg 8.2.

  • No point in using DISTINCT here.

  • Provide a column definition list for your INSERT. Else it can break in confusing ways, when you change the table later.

  • If rows in the two legs of the SELECT are unique, use UNION ALL instead of UNION. No point in trying to fold duplicates.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top