Như @Pavel đã giải thích, không chỉ đơn giản là có thể duyệt qua một bản ghi, giống như bạn có thể duyệt qua một mảng. Nhưng có một số cách xung quanh nó - tùy thuộc vào yêu cầu chính xác của bạn. Cuối cùng, vì bạn muốn trả lại tất cả các giá trị trong cùng một cột, bạn cần truyền chúng về cùng một loại - text
là điểm chung rõ ràng, bởi vì có một văn bản đại diện cho mọi loại.
Nhanh và bẩn
Giả sử, bạn có một bảng với integer
, một text
và một date
cột.
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
Sau đó, giải pháp có thể đơn giản như:
SELECT unnest(string_to_array(trim(t::text, '()'), ','))
FROM tbl t;
Hoạt động cho hai hàng đầu tiên, nhưng không thành công đối với các trường hợp đặc biệt của hàng 3 và 4.
Bạn có thể dễ dàng giải quyết vấn đề bằng dấu phẩy trong biểu diễn văn bản:
SELECT unnest(('{' || trim(t::text, '()') || '}')::text[])
FROM tbl t
WHERE a < 4;
Điều này sẽ hoạt động tốt - ngoại trừ dòng 4 có dấu ngoặc kép trong biểu diễn văn bản. Chúng được thoát ra bằng cách nhân đôi chúng lên. Nhưng hàm tạo mảng sẽ cần chúng được thoát bằng \
. Không chắc tại sao lại có sự không tương thích này ...
SELECT ('{' || trim(t::text, '()') || '}') FROM tbl t WHERE a = 4
Lợi nhuận:
{4,""",4,""ex,""",2012-10-04}
Nhưng bạn sẽ cần:
SELECT '{4,"\",4,\"ex,\"",2012-10-04}'::text[]; -- works
Giải pháp thích hợp
Nếu bạn biết trước tên cột, một giải pháp sạch sẽ rất đơn giản:
SELECT unnest(ARRAY[a::text,b::text,c::text])
FROM tbl
Vì bạn hoạt động trên các bản ghi thuộc loại biết rõ, bạn chỉ có thể truy vấn danh mục hệ thống:
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
Đặt điều này trong một hàm với SQL động:
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$;
Gọi:
SELECT unnest_table('tbl') AS val
Lợi nhuận:
val
-----
1
1text
2012-10-01
2
2text
2012-10-02
3
,3,ex,
2012-10-03
4
",4,"ex,"
2012-10-04
Điều này hoạt động mà không cần cài đặt các mô-đun bổ sung. Một tùy chọn khác là cài đặt tiện ích mở rộng hstore và sử dụng nó như @Craig demo.