【问题标题】:EXECUTE...USING statement in PL/pgSQL doesn't work with record type?PL/pgSQL 中的 EXECUTE...USING 语句不适用于记录类型?
【发布时间】:2010-01-20 20:43:40
【问题描述】:

我正在尝试在 PL/PgSQL 中编写一个函数,该函数必须与它作为参数接收的表一起工作。

我在函数定义中使用 EXECUTE..INTO..USING 语句来构建动态查询(这是我知道的唯一方法)但是......我遇到了 RECORD 数据类型的问题。

让我们考虑下面的(极其简化的)示例。

 -- A table with some values.
 DROP TABLE IF EXISTS table1;
 CREATE TABLE table1 (
     code INT,
     descr TEXT
 );

INSERT INTO table1 VALUES ('1','a');
INSERT INTO table1 VALUES ('2','b');


-- The function code. 
DROP FUNCTION IF EXISTS foo (TEXT);
CREATE FUNCTION foo (tbl_name TEXT) RETURNS VOID AS $$
DECLARE 
    r RECORD;
    d TEXT;
BEGIN
    FOR r IN
    EXECUTE 'SELECT * FROM ' || tbl_name
    LOOP
    --SELECT r.descr INTO d; --IT WORK
    EXECUTE 'SELECT ($1)' || '.descr' INTO d USING r; --IT DOES NOT WORK
    RAISE NOTICE '%', d;
END LOOP;

END;
$$ LANGUAGE plpgsql STRICT;

-- Call foo function on table1
SELECT foo('table1');

输出如下错误:

错误:无法识别记录数据类型中的列“descr”

虽然我使用的语法对我来说似乎是有效的。我不能使用静态选择(在示例中注释),因为我想动态引用列名。

所以..有人知道上面的代码有什么问题吗?

【问题讨论】:

    标签: postgresql plpgsql


    【解决方案1】:

    这是真的。您不能在 PL/pgSQL 空间之外使用类型记录。

    RECORD 值仅在 plpgsql 中有效。

    你可以的

    EXECUTE 'SELECT $1.descr' INTO d USING r::text::xx;
    

    【讨论】:

    • 好吧,很抱歉,您的代码通过将“xx”替换为“table1”来工作。但是这样我就不能动态地指定表名。所以正确的答案是:“EXECUTE 'SELECT $1::text::table1.descr' INTO d USING r;”。非常感谢!
    • 我可以使用 EXECUTE 'SELECT ($1::xx).descr' INTO d USING r; 并避免使用 text 演员表。
    【解决方案2】:

    $1 应该在 || 之内,就像 || $1 || 一样,并适当地给空格,然后它会起作用。

    BEGIN
    
    EXECUTE ' delete from  ' ||  quote_ident($1)  || ' where condition ';
    
    END;
    

    【讨论】:

    • 有问题的问题是如何以 reflective 方式(按名称,使用字符串连接)获取 RECORD 字段。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-18
    • 2013-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多