如何在 PL/pgSQL 中获取动态生成的字段名称的值

Posted

技术标签:

【中文标题】如何在 PL/pgSQL 中获取动态生成的字段名称的值【英文标题】:How to get the value of a dynamically generated field name in PL/pgSQL 【发布时间】:2016-10-01 15:06:23 【问题描述】:

示例代码精简了演示问题的基本要素:

CREATE OR REPLACE FUNCTION mytest4() RETURNS TEXT AS $$
DECLARE
   wc_row wc_files%ROWTYPE;
   fieldName TEXT;
BEGIN
    SELECT * INTO wc_row FROM wc_files WHERE "fileNumber" = 17117;
 -- RETURN wc_row."fileTitle"; -- This works. I get the contents of the field.
    fieldName := 'fileTitle';
 -- RETURN format('wc_row.%I',fieldName); -- This returns 'wc_row."fileTitle"'
                                          -- but I need the value of it instead.
    RETURN EXECUTE format('wc_row.%I',fieldName); -- This gives a syntax error.
 END;
$$ LANGUAGE plpgsql; 

在这种情况下如何获取动态生成的字段名称的值?

【问题讨论】:

在这种情况下使用EXECUTE语句的正确方法是:execute format('select $1.%I',fieldName) into result using wc_row;然后return result;(应声明变量result 太棒了!我为此挣扎了好几个小时。谢谢!!! 【参考方案1】:

使用函数to_json() 的技巧,它对于复合类型返回一个以列名作为键的json 对象:

create or replace function mytest4() 
returns text as $$
declare
   wc_row wc_files;
   fieldname text;
begin
    select * into wc_row from wc_files where "filenumber" = 17117;
    fieldname := 'filetitle';
    return to_json(wc_row)->>fieldname;
end;
$$ language plpgsql; 

【讨论】:

【参考方案2】:

你不需要技巧。 EXECUTE 做你需要的,你已经在正确的轨道上。但是RETURN EXECUTE ... 不是合法的语法。

CREATE OR REPLACE FUNCTION mytest4(OUT my_col text) AS
$func$
DECLARE
   field_name text := 'fileTitle';
BEGIN
   EXECUTE format('SELECT %I FROM wc_files WHERE "fileNumber" = 17117', field_name)
   INTO my_col;  -- data type coerced to text automatically.
END
$func$  LANGUAGE plpgsql; 
1234563 > 价值观。

使用format() 方便地转义标识符并避免 SQL 注入。提供标识符名称区分大小写!在这种情况下,filetitlefileTitle 不同。

Are PostgreSQL column names case-sensitive?

使用OUT 参数来简化您的代码。

【讨论】:

以上是关于如何在 PL/pgSQL 中获取动态生成的字段名称的值的主要内容,如果未能解决你的问题,请参考以下文章

如何在 PL/pgSQL 中的动态选择查询中使用迭代器变量?

在 PL/pgSQL 中插入后获取默认序列值

在 PL/PGSQL 动态 SQL 内部函数中引用局部变量

如何纠正 PL/pgSQL 中缺少引用的“一对多表”?

使用 PL/pgSQL 在 PostgreSQL 中将多个字段作为记录返回

PL/pgSQL 重启生成序列