PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Buat tabel dinamis dari fungsi di PostgreSQL

Solusi Anda adalah cara yang layak. Saya sebagian besar menulis ulang fungsi plpgsql Anda untuk penyederhanaan / kinerja / keterbacaan / keamanan.

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;

Ini berfungsi untuk PostgreSQL 9.1 atau lebih baru.

Untuk hal 8.4 atau nanti ganti

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

dengan:

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

Untuk versi bahkan lebih lama dari itu buat fungsi agregat seperti ini:

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
);

Dan kemudian tulis:

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

Juga:

DROP TABLE IF EXISTS tmptable;

Klausa "JIKA ADA" diperkenalkan dengan versi 8.2 .
Jika Anda harus menggunakan versi bahkan lebih tua dari itu seharusnya kamu bisa:

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

Tingkatkan!

Lihat kebijakan pembuatan versi proyek PostgreSQL . Versi 8.0.1 adalah versi yang sangat buggy. Saya akan sangat menyarankan Anda untuk meng-upgrade. Jika Anda tidak dapat meningkatkan ke versi utama yang lebih baru, setidaknya tingkatkan ke rilis titik terbaru untuk alasan keamanan, 8.0.26 dalam kasus Anda. Ini dapat dilakukan di tempat, tanpa mengubah apa pun.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. psql mengembalikan 'anonim' dalam larik hasil

  2. Perbarui kolom tabel dengan kolom tabel lain di PostgreSQL

  3. Postgres:Mengapa kinerjanya sangat buruk pada subpilihan dengan Offset/Batas

  4. Cara menyembunyikan dekorasi set hasil dalam output Psql

  5. Memantau PostgreSQL di Lingkungan Hibrida