Wie @Pavel erklärte, ist es nicht einfach möglich, einen Datensatz zu durchlaufen, wie Sie ein Array durchlaufen könnten. Es gibt jedoch mehrere Möglichkeiten, dies zu umgehen - je nach Ihren genauen Anforderungen. Da Sie alle Werte in derselben Spalte zurückgeben möchten, müssen Sie sie letztendlich in denselben Typ umwandeln – text
ist die offensichtliche Gemeinsamkeit, da es für jeden Typ eine Textdarstellung gibt.
Schnell und schmutzig
Angenommen, Sie haben eine Tabelle mit einer integer
, ein text
und ein date
Säule.
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
Dann kann die Lösung so einfach sein:
SELECT unnest(string_to_array(trim(t::text, '()'), ','))
FROM tbl t;
Funktioniert für die ersten beiden Zeilen, schlägt aber für die Sonderfälle Zeile 3 und 4 fehl.
Sie können das Problem leicht mit Kommas in der Textdarstellung lösen:
SELECT unnest(('{' || trim(t::text, '()') || '}')::text[])
FROM tbl t
WHERE a < 4;
Dies würde gut funktionieren - mit Ausnahme von Zeile 4, die doppelte Anführungszeichen in der Textdarstellung enthält. Diese werden durch Verdoppelung umgangen. Aber der Array-Konstruktor müsste sie durch \
maskieren . Nicht sicher, warum diese Inkompatibilität da ist ...
SELECT ('{' || trim(t::text, '()') || '}') FROM tbl t WHERE a = 4
Ausbeuten:
{4,""",4,""ex,""",2012-10-04}
Aber Sie bräuchten:
SELECT '{4,"\",4,\"ex,\"",2012-10-04}'::text[]; -- works
Richtige Lösung
Wenn Sie die Spaltennamen vorher wüssten, wäre eine saubere Lösung einfach:
SELECT unnest(ARRAY[a::text,b::text,c::text])
FROM tbl
Da Sie mit Datensätzen bekannter Art arbeiten, können Sie einfach den Systemkatalog abfragen:
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
Fügen Sie dies in eine Funktion mit dynamischem SQL ein:
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$;
Aufruf:
SELECT unnest_table('tbl') AS val
Rückgabe:
val
-----
1
1text
2012-10-01
2
2text
2012-10-02
3
,3,ex,
2012-10-03
4
",4,"ex,"
2012-10-04
Dies funktioniert ohne Installation zusätzlicher Module. Eine andere Möglichkeit besteht darin, die hstore-Erweiterung zu installieren und sie so zu verwenden, wie @Craig demonstriert.