PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Ulangi kolom RECORD

Seperti yang dijelaskan @Pavel, tidak mungkin untuk melintasi catatan, seperti Anda dapat melintasi larik. Tetapi ada beberapa cara untuk mengatasinya - tergantung pada kebutuhan Anda. Pada akhirnya, karena Anda ingin mengembalikan semua nilai di kolom yang sama, Anda harus memasukkannya ke jenis yang sama - text adalah kesamaan yang jelas, karena ada representasi teks untuk setiap jenis.

Cepat dan kotor

Katakanlah, Anda memiliki tabel dengan integer , sebuah text dan date kolom.

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

Maka solusinya bisa sederhana seperti:

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

Berfungsi untuk dua baris pertama, tetapi gagal untuk kasus khusus baris 3 dan 4.
Anda dapat dengan mudah menyelesaikan masalah dengan koma dalam representasi teks:

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

Ini akan berfungsi dengan baik - kecuali untuk baris 4 yang memiliki tanda kutip ganda dalam representasi teks. Mereka lolos dengan menggandakannya. Tetapi konstruktor array akan membutuhkan mereka lolos dengan \ . Tidak yakin mengapa ketidakcocokan ini ada ...

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

Hasil:

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

Tetapi Anda akan membutuhkan:

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

Solusi yang tepat

Jika Anda mengetahui nama kolom sebelumnya, solusi bersihnya sederhana:

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

Karena Anda beroperasi pada catatan jenis yang diketahui dengan baik, Anda dapat menanyakan katalog sistem:

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

Masukkan ini ke dalam fungsi dengan SQL dinamis:

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$;

Telepon:

SELECT unnest_table('tbl') AS val

Pengembalian:

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

Ini berfungsi tanpa menginstal modul tambahan. Opsi lainnya adalah menginstal ekstensi hstore dan menggunakannya seperti yang ditunjukkan oleh @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. Membandingkan Load Balancer untuk PostgreSQL

  2. Pemetaan hibernasi antara Enum PostgreSQL dan Java enum

  3. Hitung Maks Jumlah dari bidang beranotasi di atas yang dikelompokkan menurut kueri di Django ORM?

  4. Ikat param array ke kueri asli

  5. Mengapa saya tidak bisa menggunakan alias kolom dalam ekspresi SELECT berikutnya?