sql >> データベース >  >> RDS >> PostgreSQL

RECORDの列をループします

    @Pavelが説明したように、配列をトラバースできるように、レコードをトラバースすることは単純に可能ではありません。ただし、正確な要件に応じて、いくつかの方法があります。最終的には、同じ列のすべての値を返したいので、それらを同じタイプ(text)にキャストする必要があります すべてのタイプにテキスト表現があるため、これは明らかな共通点です。

    速くて汚い

    たとえば、integerを含むテーブルがあるとします。 、text およびdate 桁。

    CREATE TEMP TABLE tbl(a int, b text, c date);
    INSERT INTO tbl VALUES
     (1, '1text',     '2012-10-01')
    ,(2, '2text',     '2012-10-02')
    ,(3, ',3,ex,',    '2012-10-03')  -- text with commas
    ,(4, '",4,"ex,"', '2012-10-04')  -- text with commas and double quotes
    

    その場合、解決策は次のように単純になります。

    SELECT unnest(string_to_array(trim(t::text, '()'), ','))
    FROM   tbl t;
    

    最初の2行では機能しますが、行3と4の特殊なケースでは失敗します。
    テキスト表現のカンマを使用すると、問題を簡単に解決できます。

    SELECT unnest(('{' || trim(t::text, '()') || '}')::text[])
    FROM   tbl t
    WHERE  a < 4;
    

    これは問題なく機能します。ただし、テキスト表現に二重引用符が含まれている4行目を除きます。それらを2倍にすることでそれらは逃げられます。ただし、配列コンストラクターでは、\でエスケープする必要があります。 。この非互換性が存在する理由がわかりません...

    SELECT ('{' || trim(t::text, '()') || '}') FROM tbl t WHERE a = 4
    

    収量:

    {4,""",4,""ex,""",2012-10-04}
    

    ただし、次のものが必要になります:

    SELECT '{4,"\",4,\"ex,\"",2012-10-04}'::text[];  -- works
    

    適切なソリューション

    列名を事前に知っていれば、クリーンな解決策は簡単です。

    SELECT unnest(ARRAY[a::text,b::text,c::text])
    FROM tbl
    

    よく知られているタイプのレコードを操作するため、システムカタログをクエリするだけです。

    SELECT string_agg(a.attname || '::text', ',' ORDER  BY a.attnum)
    FROM   pg_catalog.pg_attribute a 
    WHERE  a.attrelid = 'tbl'::regclass
    AND    a.attnum > 0
    AND    a.attisdropped = FALSE
    

    これを動的SQLを使用する関数に入れます:

    CREATE OR REPLACE FUNCTION unnest_table(_tbl text)
      RETURNS SETOF text LANGUAGE plpgsql AS
    $func$
    BEGIN
    
    RETURN QUERY EXECUTE '
    SELECT unnest(ARRAY[' || (
        SELECT string_agg(a.attname || '::text', ',' ORDER  BY a.attnum)
        FROM   pg_catalog.pg_attribute a 
        WHERE  a.attrelid = _tbl::regclass
        AND    a.attnum > 0
        AND    a.attisdropped = false
        ) || '])
    FROM   ' || _tbl::regclass;
    
    END
    $func$;
    

    電話:

    SELECT unnest_table('tbl') AS val
    

    返品:

    val
    -----
    1
    1text
    2012-10-01
    2
    2text
    2012-10-02
    3
    ,3,ex,
    2012-10-03
    4
    ",4,"ex,"
    2012-10-04
    

    これは、追加のモジュールをインストールしなくても機能します。もう1つのオプションは、hstore拡張機能をインストールして、@Craigが示すように使用することです。



    1. あなたを驚かせるかもしれないデータベースパフォーマンスモニタリングについての10の事実

    2. 列の名前をSQLServer2008に変更します

    3. DATE列にjava.sql.Timestampを渡すと、Oracleが非常に遅いのはなぜですか?

    4. 壊れたUTF-8エンコーディングの修正