PostgreSQL
 sql >> база данни >  >> RDS >> PostgreSQL

Превъртете през колоните на RECORD

Както @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.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Какъв е най-бързият начин да направите групово вмъкване в Postgres?

  2. Как да импортирам данни от CSV в таблица на Postgres с помощта на pgAdmin 3?

  3. Как да възстановите непоследователен PostgreSQL Slave

  4. Заявката за избор с ограничение за отместване е твърде бавна

  5. Какъв е редът на записите в таблица със съставен първичен ключ