PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Създайте динамична таблица от функция в PostgreSQL

Вашето решение е жизнеспособен начин. До голяма степен пренаписах вашата функция plpgsql за опростяване/производителност/четимост/сигурност.

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;

Това работи за PostgreSQL 9.1 или по-нова версия.

За стр. 8.4 или по-късно заменете

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

с:

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

За версиидори по-стари отколкото да създадете обобщена функция като тази:

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

И след това напишете:

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

Също така:

DROP TABLE IF EXISTS tmptable;

Клаузата „АКО СЪЩЕСТВУВА“ беше въведена с версия 8.2 .
Ако трябва да използвате версия още по-стара отколкото трябва, можете да:

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

Надградете!

Разгледайте политиката за версии на проекта PostgreSQL . Версия 8.0.1 е особено бъгова версия. Бихсилно съветвам ви да надстроите. Ако не можете да надстроите до по-нова основна версия, надстройте поне до най-новата точкова версия от съображения за сигурност, 8.0.26 във вашия случай. Това може да се направи на място, без да се променя нищо друго.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Asp.net MVC4, PostgreSQL и SimpleMembership

  2. Как да вмъкнете списък на Python в таблицата на Postgres

  3. Вътрешно присъединяване срещу правене на клауза where в

  4. Как да направя заявка за низ от JSON въз основа на друг низ в рамките на JSON в PostgreSQL?

  5. Заявките на Java срещу PGPool II причиняват грешки при неименуван подготвен оператор