@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が示すように使用することです。