Seperti yang dijelaskan @Pavel, tidak mungkin untuk melintasi catatan, seperti Anda dapat melintasi larik. Tetapi ada beberapa cara untuk mengatasinya - tergantung pada kebutuhan Anda. Pada akhirnya, karena Anda ingin mengembalikan semua nilai di kolom yang sama, Anda harus memasukkannya ke jenis yang sama - text
adalah kesamaan yang jelas, karena ada representasi teks untuk setiap jenis.
Cepat dan kotor
Katakanlah, Anda memiliki tabel dengan integer
, sebuah text
dan date
kolom.
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
Maka solusinya bisa sederhana seperti:
SELECT unnest(string_to_array(trim(t::text, '()'), ','))
FROM tbl t;
Berfungsi untuk dua baris pertama, tetapi gagal untuk kasus khusus baris 3 dan 4.
Anda dapat dengan mudah menyelesaikan masalah dengan koma dalam representasi teks:
SELECT unnest(('{' || trim(t::text, '()') || '}')::text[])
FROM tbl t
WHERE a < 4;
Ini akan berfungsi dengan baik - kecuali untuk baris 4 yang memiliki tanda kutip ganda dalam representasi teks. Mereka lolos dengan menggandakannya. Tetapi konstruktor array akan membutuhkan mereka lolos dengan \
. Tidak yakin mengapa ketidakcocokan ini ada ...
SELECT ('{' || trim(t::text, '()') || '}') FROM tbl t WHERE a = 4
Hasil:
{4,""",4,""ex,""",2012-10-04}
Tetapi Anda akan membutuhkan:
SELECT '{4,"\",4,\"ex,\"",2012-10-04}'::text[]; -- works
Solusi yang tepat
Jika Anda mengetahui nama kolom sebelumnya, solusi bersihnya sederhana:
SELECT unnest(ARRAY[a::text,b::text,c::text])
FROM tbl
Karena Anda beroperasi pada catatan jenis yang diketahui dengan baik, Anda dapat menanyakan katalog sistem:
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
Masukkan ini ke dalam fungsi dengan SQL dinamis:
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$;
Telepon:
SELECT unnest_table('tbl') AS val
Pengembalian:
val
-----
1
1text
2012-10-01
2
2text
2012-10-02
3
,3,ex,
2012-10-03
4
",4,"ex,"
2012-10-04
Ini berfungsi tanpa menginstal modul tambahan. Opsi lainnya adalah menginstal ekstensi hstore dan menggunakannya seperti yang ditunjukkan oleh @Craig.