sql >> Databasteknik >  >> RDS >> PostgreSQL

Skapa dynamisk tabell från funktion i PostgreSQL

Din lösning är ett hållbart sätt. Jag skrev om till stor del din plpgsql-funktion för förenkling / prestanda / läsbarhet / säkerhet.

CREATE OR REPLACE FUNCTION f_taxamount()
 RETURNS void AS
$BODY$
DECLARE
    rec record;
BEGIN

    DROP TABLE IF EXISTS tmptable;

    EXECUTE 'CREATE TABLE tmptable (invoiceid integer PRIMARY KEY, '
        || (
           SELECT string_agg(col || ' numeric(9,2) DEFAULT 0', ', ')
           FROM  (
              SELECT quote_ident(lower(replace(taxname,' ','_'))) AS col
              FROM   tbltaxamount
              GROUP  BY 1
              ORDER  BY 1
              ) x
           )
        || ')';

    EXECUTE '
        INSERT INTO tmptable (invoiceid)
        SELECT DISTINCT invoiceid FROM tbltaxamount';

    FOR rec IN
        SELECT taxname, taxamt, invoiceid FROM tbltaxamount ORDER BY invoiceid
    LOOP
        EXECUTE '
            UPDATE tmptable
            SET ' || quote_ident(lower(replace(rec.taxname,' ','_')))
                  || ' = '|| rec.taxamt || ' 
            WHERE invoiceid = ' || rec.invoiceid;
    END LOOP;

END;
$BODY$ LANGUAGE plpgsql;

Detta fungerar för PostgreSQL 9.1 eller senare.

För sid 8.4 eller senare byt ut

SELECT string_agg(col || ' numeric(9,2) DEFAULT 0', ', ')

med:

SELECT array_to_string(array_agg(col || ' numeric(9,2) DEFAULT 0'), ', ')

För versioner ännu äldre än att skapa en aggregatfunktion så här:

CREATE OR REPLACE FUNCTION f_concat_comma(text, text)
  RETURNS text AS
$BODY$
BEGIN
RETURN ($1 || ', '::text) || $2;
END;
$BODY$
  LANGUAGE plpgsql IMMUTABLE;

CREATE AGGREGATE concat_comma(text) (
  SFUNC=f_concat_comma,
  STYPE=text
);

Och skriv sedan:

SELECT concat_comma(col || ' numeric(9,2) DEFAULT 0')

Även:

DROP TABLE IF EXISTS tmptable;

Klausulen "OM FINNS" introducerades med version 8.2 .
Om du ska använda en ännu äldre version än vad du borde kan du:

IF EXISTS (
    SELECT *
    FROM   pg_catalog.pg_class
    WHERE  oid = 'tmptable'::regclass
    AND    relkind = 'r')
THEN
    DROP TABLE tmptable;
END IF;
*/

Uppgradera!

Ta en titt på versionspolicyn för PostgreSQL-projektet . Version 8.0.1 är en särskilt buggig version. Jag skulle starkt råder dig att uppgradera. Om du inte kan uppgradera till en nyare huvudversion, uppgradera åtminstone till den senaste punktutgåvan av säkerhetsskäl, 8.0.26 i ditt fall. Detta kan göras på plats, utan att ändra något annat.



  1. När ska jag använda MySQL-transaktioner?

  2. Hur man hämtar frågeplansinformation från Postgres till JDBC

  3. Få alla främmande nycklar med JDBC

  4. MySQL - VÄLJ SOM I WHERE