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);
>使用regclass
作为输入参数类型,因此只能使用有效的表名开头并排除sql注入.如果您应该提供非法的表名,该函数也会更早,更优雅地失败.
>使用OUT参数(pk_new)来简化语法.
>无需手动确定主键的下一个值.它会自动插入并在事后返回.这不仅更简单,更快,还可以避免浪费或无序的序列号.
>使用format()
简化动态查询字符串的组装,使其不易出错.请注意我如何分别使用标识符和字符串的位置参数.
>我建立在您隐含的假设基础上,即允许表具有整数类型的单个主键列,其列默认值.通常为serial
列.
>该函数的关键元素是最终的INSERT:
>使用子选择中的#=
operator将覆盖值与现有行合并,并立即分解生成的行.>然后,您只能选择主SELECT中的相关列.>让Postgres为PK分配默认值,并使用RETURNING子句将其恢复.>直接将返回值写入OUT参数.>所有在一个sql命令中完成,通常是最快的.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。