Както @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;
Работи за първите два реда, но не работи за специалните случаи на ред 3 и 4.
Можете лесно да решите проблема със запетаи в текстовото представяне:
SELECT unnest(('{' || trim(t::text, '()') || '}')::text[])
FROM tbl t
WHERE a < 4;
Това би работило добре - с изключение на ред 4, който има двойни кавички в текстовото представяне. Те се измъкват чрез удвояването им. Но конструкторът на масива ще има нужда от екраниране с \
. Не знам защо има тази несъвместимост ...
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.