postgresql – EXECUTE … INTO … PL / pgSQL中的USING语句无法执行到记录中?

我正在尝试在PL / pgSQL中编写一个函数区域,它循环遍历hstore并将记录的列(hstore的键)设置为特定值(hstore的值).我正在使用Postgres 9.1.

hstore看起来像:’“column1”=>“value1”,“column2”=>“value2”’

一般来说,这是我想要的一个函数,它接受一个hstore并且有一个带有要修改的值的记录:

FOR my_key,my_value IN
    SELECT key,value
      FROM EACH( in_hstore )
LOOP
    EXECUTE 'SELECT $1'
       INTO my_row.my_key
      USING my_value;
END LOOP;

我在这段代码中得到的错误:

“myrow”没有字段“my_key”.我一直在寻找解决方案已经有一段时间了,但是我试图获得相同结果的其他一切都没有奏效.

解决方法

比您发布的答案更简单的替代方案.应该表现得更好.

此函数从给定表(in_table_name)和主键值(in_row_pk)中检索一行,并将其作为新行插入到同一个表中,并替换一些值(in_override_values).返回默认的新主键值(pk_new).

CREATE OR REPLACE FUNCTION f_clone_row(in_table_name regclass,in_row_pk int,in_override_values hstore,OUT pk_new int) AS
$func$
DECLARE
   _pk   text;  -- name of PK column
   _cols text;  -- list of names of other columns
BEGIN

-- Get name of PK column
SELECT INTO _pk  a.attname
FROM   pg_catalog.pg_index     i
JOIN   pg_catalog.pg_attribute a ON a.attrelid = i.indrelid
                                AND a.attnum   = i.indkey[0]  -- 1 PK col!
WHERE  i.indrelid = 't'::regclass
AND    i.indisprimary;

-- Get list of columns excluding PK column
_cols := array_to_string(ARRAY(
      SELECT quote_ident(attname)
      FROM   pg_catalog.pg_attribute
      WHERE  attrelid = in_table_name -- regclass used as OID
      AND    attnum > 0               -- exclude system columns
      AND    attisdropped = FALSE     -- exclude dropped columns
      AND    attname <> _pk           -- exclude PK column
      ),',');

-- INSERT cloned row with override values,returning new PK
EXECUTE format('
   INSERT INTO %1$I (%2$s)
   SELECT %2$s
   FROM  (SELECT (t #= $1).* FROM %1$I t WHERE %3$I = $2) x
   RETURNING %3$I',in_table_name,_cols,_pk)
USING   in_override_values,in_row_pk -- use override values directly
INTO    pk_new;                       -- return new pk directly

END
$func$LANGUAGE plpgsql;

呼叫:

SELECT f_clone_row('t',1,'"col1"=>"foo_new","col2"=>"bar_new"'::hstore);

SQL Fiddle.

>使用regclass作为输入参数类型,因此只能使用有效的表名开头并排除SQL注入.如果您应该提供非法的表名,该函数也会更早,更优雅地失败.
>使用OUT参数(pk_new)来简化语法.
>无需手动确定主键的下一个值.它会自动插入并在事后返回.这不仅更简单,更快,还可以避免浪费或无序的序列号.
>使用format()简化动态查询字符串的组装,使其不易出错.请注意我如何分别使用标识符和字符串的位置参数.
>我建立在您隐含的假设基础上,即允许表具有整数类型的单个主键列,其列默认值.通常为serial列.
>该函数的关键元素是最终的INSERT:

>使用子选择中的#= operator将覆盖值与现有行合并,并立即分解生成的行.>然后,您只能选择主SELECT中的相关列.>让Postgres为PK分配默认值,并使用RETURNING子句将其恢复.>直接将返回值写入OUT参数.>所有在一个SQL命令中完成,通常是最快的.

相关文章

文章浏览阅读601次。Oracle的数据导入导出是一项基本的技能,...
文章浏览阅读553次。开头还是介绍一下群,如果感兴趣polardb...
文章浏览阅读3.5k次,点赞3次,收藏7次。折腾了两个小时多才...
文章浏览阅读2.7k次。JSON 代表 JavaScript Object Notation...
文章浏览阅读2.9k次,点赞2次,收藏6次。navicat 连接postgr...
文章浏览阅读1.4k次。postgre进阶sql,包含分组排序、JSON解...