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;
    

    これはPostgreSQL9.1以降で機能します。

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

    「IFEXISTS」という句は、バージョン 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. MySQLのテーブルのすべての列を削除するにはどうすればよいですか?

    2. SQLServer2008およびOffice2007を使用したVisualStudio2010の適切なインストール順序?

    3. MySQLでSoundex()サブストリングを検索する方法は?

    4. MySQLのENUMタイプの列にメンバーを追加するにはどうすればよいですか?