PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Przechodź przez kolumny RECORD

Jak wyjaśnił @Pavel, nie jest po prostu możliwe przechodzenie przez rekord, tak jakbyś przemierzał tablicę. Ale jest kilka sposobów na obejście tego - w zależności od twoich dokładnych wymagań. Ostatecznie, ponieważ chcesz zwrócić wszystkie wartości w tej samej kolumnie, musisz rzutować je na ten sam typ - text jest oczywistą wspólną płaszczyzną, ponieważ istnieje reprezentacja tekstowa dla każdego typu.

Szybko i brudno

Powiedzmy, że masz tabelę z integer , text i date kolumna.

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

Wtedy rozwiązanie może być proste, jak:

SELECT unnest(string_to_array(trim(t::text, '()'), ','))
FROM   tbl t;

Działa dla pierwszych dwóch wierszy, ale nie działa w szczególnych przypadkach wierszy 3 i 4.
Możesz łatwo rozwiązać problem za pomocą przecinków w reprezentacji tekstowej:

SELECT unnest(('{' || trim(t::text, '()') || '}')::text[])
FROM   tbl t
WHERE  a < 4;

To działałoby dobrze - z wyjątkiem wiersza 4, który zawiera podwójne cudzysłowy w reprezentacji tekstowej. Tym unika się poprzez ich podwojenie. Ale konstruktor tablicy potrzebowałby ich ucieczki przez \ . Nie jestem pewien, dlaczego istnieje ta niezgodność ...

SELECT ('{' || trim(t::text, '()') || '}') FROM tbl t WHERE a = 4

Plony:

{4,""",4,""ex,""",2012-10-04}

Ale potrzebujesz:

SELECT '{4,"\",4,\"ex,\"",2012-10-04}'::text[];  -- works

Właściwe rozwiązanie

Gdybyś wcześniej znał nazwy kolumn, proste rozwiązanie byłoby proste:

SELECT unnest(ARRAY[a::text,b::text,c::text])
FROM tbl

Ponieważ operujesz na rekordach znanego typu, możesz po prostu przeszukać katalog systemowy:

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

Umieść to w funkcji z dynamicznym 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$;

Zadzwoń:

SELECT unnest_table('tbl') AS val

Zwroty:

val
-----
1
1text
2012-10-01
2
2text
2012-10-02
3
,3,ex,
2012-10-03
4
",4,"ex,"
2012-10-04

Działa to bez instalowania dodatkowych modułów. Inną opcją jest zainstalowanie rozszerzenia hstore i używanie go tak, jak demonstruje @Craig.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Importuj zrzut MySQL do bazy danych PostgreSQL

  2. Błąd Postgresa podczas aktualizowania danych w kolumnie

  3. Korzystanie z zapytania Hibernate:dwukropek jest traktowany jako parametr / dwukropek ucieczki

  4. Jak wyświetlić bazy danych i tabele w PostgreSQL za pomocą psql

  5. Jak porównać dane między dwiema bazami danych w PostgreSQL?