sql >> Databáze >  >> RDS >> PostgreSQL

Vytvořte dynamickou tabulku z funkce v PostgreSQL

Vaše řešení je schůdná cesta. Z velké části jsem přepsal vaši funkci plpgsql pro zjednodušení / výkon / čitelnost / zabezpečení.

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;

Toto funguje pro PostgreSQL 9.1 nebo novější.

Pro str. 8.4 nebo později nahradit

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

s:

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

Pro verze ještě starší než to vytvoří agregační funkci, jako je tato:

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

A pak napište:

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

Také:

DROP TABLE IF EXISTS tmptable;

Klauzule „IF EXISTS“ byla zavedena s verzí 8.2 .
Pokud byste měli použít verzi ještě starší než byste měli, můžete:

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

Upgradujte!

Podívejte se na zásady verzování projektu PostgreSQL . Verze 8.0.1 je obzvláště zabugovaná verze. Já bych silně doporučit upgrade. Pokud nemůžete upgradovat na novější hlavní verzi, upgradujte z bezpečnostních důvodů alespoň na nejnovější verzi, ve vašem případě 8.0.26. To lze provést na místě, aniž byste cokoli jiného měnili.



  1. Příliš velká velikost řádku v dotazu na vytvoření tabulky mysql

  2. Jak získat počet nevyužitých/použitých připojení ve fondu připojení nodejs mysql?

  3. Odeslání formuláře, mysql a php

  4. Jak převést html do pdf pomocí php?