【问题标题】:Reference Local Variable In PL/PGSQL Dynamic SQL Inside Function在 PL/PGSQL 动态 SQL 内部函数中引用局部变量
【发布时间】:2015-06-10 15:33:28
【问题描述】:

我有一个用于数据处理的 PL/PGSQL 函数。我需要先从表中选择每一行,然后检索每列的列名和相关值。所以基本上我将记录取消旋转到水平状态。这是必要的,因为它们将进入键/值存储而不是水平存储。

这是我目前所拥有的函数的摘要:

CREATE OR REPLACE FUNCTION myfunc()
    RETURNS INT AS 
    $BODY$
DECLARE 
x record; 
aesql varchar;
aeval varchar;
y information_schema.columns%rowtype;
BEGIN
    FOR x IN
    SELECT * FROM mytable
    LOOP
        FOR y in
        SELECT * FROM information_schema.columns where table_schema = 'public' AND table_name = 'mytable'
        loop                                
            execute 'select cast(x.'||y.column_name||' as varchar) into aeval';
        end loop;
        -- add processing for aeval once the dynamic sql is figured out                     
    END LOOP;   
    RETURN 1;
END;
$BODY$ LANGUAGE plpgsql VOLATILE;

我已经解决了这么多问题,以至于我的理解是,要执行一条执行语句,它应该是一个 CRUD 查询或类似的东西。我尝试直接分配的任何查询,例如

execute 'aeval := x.'||y.column_name;

如果我使用 ':aeval' 等,'aeval' 或 ':' 的语法错误失败。

那么有谁知道这是否可行,以及我可以如何执行这个动态 sql?总结一下,我需要获取记录 x 的值,但我只知道列名。

当我尝试运行该函数时,我收到错误:

错误:表“x”缺少 FROM 子句条目其中:PL/pgSQL 在 EXECUTE 语句中执行 myfunc() 第 23 行

【问题讨论】:

    标签: sql postgresql function plpgsql dynamic-sql


    【解决方案1】:

    这个有趣的查询:

    select
        translate(string_to_array(mytable.*::text,',')::text,'()','')::text[]
    from mytable;
    

    将 mytable 中的行作为文本数组返回。在函数中循环数组会容易得多:

    create or replace function myfunc()
    returns setof text language plpgsql
    as $$
    declare
        eaval text;
        x text[];
    begin
        for x in
            select translate(string_to_array(mytable.*::text,',')::text,'()','')::text[] 
            from mytable
        loop
            foreach eaval in array x loop
                return next eaval;
            end loop;
            return next '-- next row --';
        end loop;
    end $$;
    
    select * from myfunc();
    

    带参数的函数 - 表名:

    create or replace function myfunc(table_name text)
    returns setof text language plpgsql
    as $$
    declare
        eaval text;
        x text[];
    begin
        for x in
            execute format($fmt$
                select translate(string_to_array(%s.*::text,',')::text,'()','')::text[] 
                from %s 
                $fmt$, 
                table_name, table_name)
        loop
            foreach eaval in array x loop
                return next eaval;
            end loop;
            return next '-- next row --';
        end loop;
    end $$;
    
    select * from myfunc('mytable');
    select * from myfunc('myschema.myanothertable');
    

    阅读更多:39.5.4. Executing Dynamic Commands9.4.1. format

    【讨论】:

    • 这很酷。如果您知道如何通过将表格指定为字符串或对象来执行此操作,那么奖励积分?例如,如果我想在几种不同类型的表上运行它怎么办?
    猜你喜欢
    • 2017-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-02
    • 1970-01-01
    • 1970-01-01
    • 2018-02-10
    相关资源
    最近更新 更多