@Pavelが説明したように、配列をトラバースできるように、レコードをトラバースすることは単に可能ではありません。ただし、正確な要件に応じて、いくつかの方法があります。最終的には、すべての値を同じ列に返す必要があるため、それらを同じ型にキャストする必要がありtext
ます。すべての型にテキスト表現があるため、これは明らかな共通点です。
速くて汚い
integer
、a、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
これは、追加のモジュールをインストールしなくても機能します。別のオプションは、hstore拡張機能をインストールし、@ Craig が示すように使用することです。