Comme @Pavel l'a expliqué, il n'est pas simplement possible de parcourir un enregistrement, comme vous pourriez parcourir un tableau. Mais il existe plusieurs façons de contourner cela - en fonction de vos besoins exacts. En fin de compte, puisque vous souhaitez renvoyer toutes les valeurs dans la même colonne, vous devez les convertir dans le même type - text
est le terrain d'entente évident, car il existe une représentation textuelle pour chaque type.
Rapide et sale
Supposons que vous ayez une table avec un integer
, un text
et une date
colonne.
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
Alors la solution peut être aussi simple que :
SELECT unnest(string_to_array(trim(t::text, '()'), ','))
FROM tbl t;
Fonctionne pour les deux premières lignes, mais échoue pour les cas particuliers des lignes 3 et 4.
Vous pouvez facilement résoudre le problème avec des virgules dans la représentation textuelle :
SELECT unnest(('{' || trim(t::text, '()') || '}')::text[])
FROM tbl t
WHERE a < 4;
Cela fonctionnerait bien - sauf pour la ligne 4 qui a des guillemets doubles dans la représentation du texte. Ceux-ci sont échappés en les doublant. Mais le constructeur de tableau aurait besoin qu'ils soient échappés par \
. Je ne sais pas pourquoi cette incompatibilité est là...
SELECT ('{' || trim(t::text, '()') || '}') FROM tbl t WHERE a = 4
Rendement :
{4,""",4,""ex,""",2012-10-04}
Mais vous auriez besoin :
SELECT '{4,"\",4,\"ex,\"",2012-10-04}'::text[]; -- works
Solution appropriée
Si vous connaissiez les noms des colonnes à l'avance, une solution propre serait simple :
SELECT unnest(ARRAY[a::text,b::text,c::text])
FROM tbl
Étant donné que vous travaillez sur des enregistrements de type bien connu, vous pouvez simplement interroger le catalogue système :
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
Mettez ceci dans une fonction avec SQL dynamique :
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$;
Appel :
SELECT unnest_table('tbl') AS val
Renvoie :
val
-----
1
1text
2012-10-01
2
2text
2012-10-02
3
,3,ex,
2012-10-03
4
",4,"ex,"
2012-10-04
Cela fonctionne sans installer de modules supplémentaires. Une autre option consiste à installer l'extension hstore et à l'utiliser comme le montre @Craig.