循环记录的列

2024-01-31

我需要循环类型RECORD按键/索引排列的项目,就像我可以使用其他编程语言中的数组结构来做到这一点。

例如:

DECLARE
    data1    record;
    data2    text;
...
BEGIN
...
FOR data1 IN
    SELECT
        *
    FROM
        sometable
LOOP

    FOR data2 IN
        SELECT
            unnest( data1 )   -- THIS IS DOESN'T WORK!
    LOOP
        RETURN NEXT data1[data2];   -- SMTH LIKE THIS
    END LOOP;

END LOOP;

正如@Pavel 所解释的,不能像遍历数组那样简单地遍历记录。但有几种方法可以解决这个问题 - 具体取决于您的具体要求。最终,由于您想要返回同一列中的所有值,因此需要将它们转换为相同的类型 -text是明显的共同点,因为每种类型都有一个文本表示。

又快又脏

假设,你有一张桌子,上面有一个integer, a text and a 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

Yields:

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

Call:

SELECT unnest_table('tbl') AS val

Returns:

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

这无需安装额外的模块即可工作。另一种选择是安装hstore http://www.postgresql.org/docs/current/interactive/hstore.html扩展并使用它就像@Craig 演示的那样 https://stackoverflow.com/a/13078982/939860.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

循环记录的列 的相关文章

随机推荐