Postgresql 表名为参数的游标的更新记录

Postgresql 表名为参数的游标的更新记录,postgresql,cursor,sql-update,plpgsql,dynamic-sql,Postgresql,Cursor,Sql Update,Plpgsql,Dynamic Sql,我正在调整一些PL/pgSQL代码,以便refcursor可以将表名作为参数。因此,我更改了以下行: declare pointCurs CURSOR FOR SELECT * from tableName for update; 关于这一点: OPEN pointCurs FOR execute 'SELECT * FROM ' || quote_ident(tableName) for update; 我调整了回路,瞧,回路通过了。现在在循环中的某个点,我需要更新光标指向的记录,我被卡

我正在调整一些PL/pgSQL代码,以便refcursor可以将表名作为参数。因此,我更改了以下行:

declare
 pointCurs CURSOR FOR SELECT * from tableName for update;
关于这一点:

OPEN pointCurs FOR execute 'SELECT * FROM ' || quote_ident(tableName) for update;
我调整了回路,瞧,回路通过了。现在在循环中的某个点,我需要更新光标指向的记录,我被卡住了。我应该如何正确地调整以下代码行

UPDATE tableName set tp_id = pos where current of pointCurs;
我修复了tableName和pos的引号,并在开头添加了EXECUTE子句,但在pointCurs的where current上出现了错误

问题: 我如何更新记录? ii该函数对来自公共架构的表正常工作,而对来自其他架构(例如trace.myname)的表则失败

非常感谢您的任何意见。

请回答我的问题 1.显式未绑定游标 不是子句,而是用于执行SQL字符串的PL/pgSQL命令。光标在命令中不可见。您需要将值传递给它

因此,不能使用特殊语法。我使用系统列来确定行,而不知道唯一列的名称。注意,ctid只保证在同一事务中是稳定的

创建或替换函数f_curs1_tbl text 返回void作为 $func$ 声明 _游标参照游标; rec记录; 开始 打开_curs以执行'SELECT*FROM'| | quote_ident_tbl以进行更新; 环 将下一个从_curs获取到rec; rec为空时退出; 提出通知“%”,rec.tbl_id; 执行格式“更新%I设置tbl_id=tbl_id+10,其中ctid=$1”,\u tbl 使用rec.ctid; 端环; 终止 $func$语言plpgsql; 还有一个变体,但它仅适用于绑定游标。我们必须在这里使用未绑定的游标

2.FOR循环中的隐式游标 plpgsql中通常不需要显式游标。改为使用FOR循环的隐式光标:

创建或替换函数f_curs2_tbl text 返回void作为 $func$ 声明 _ctid tid; 开始 对于“执行”中的“ctid”,请从“| | quote_ident_tbl”中选择ctid进行更新 环 执行格式“更新%I设置tbl_id=tbl_id+100,其中ctid=$1”,\u tbl 使用ctid; 端环; 终止 $func$语言plpgsql; 3.基于集合的方法 或者更好,如果可能的话!:重新考虑基于集合的操作方面的问题,并执行单个动态SQL命令:

-基于集合的动态SQL 创建或替换函数f_nocurs_tbl text 返回void作为 $func$ 开始 执行格式“更新%I设置tbl\U id=tbl\U id+1000”,tbl; -根据需要添加WHERE子句 终止 $func$语言plpgsql; 演示所有3种变体

答案二 模式限定的表名(如trace.myname)实际上由两个标识符组成。你必须

要么分别通过和逃离他们, 或者使用更优雅的方法使用regclass类型: 创建或替换函数f_nocurs_tbl regclass 返回void作为 $func$ 开始 执行格式“更新%s设置tbl\U id=tbl\U id+1000”,tbl; 终止 $func$语言plpgsql; 我从%I切换到%s,因为在自动转换为文本时,regclass参数会自动正确转义。 更多详情请参见本相关答案:


如果表名是动态的,您如何知道列名为tp_id?回答得很好。谢谢你花了这么多时间在这上面。我将跟随你的帖子寻找智慧。快速跟进问题:执行格式“UPDATE%I SET tbl_id=tbl_id+100,其中ctid=1”的复杂性是什么?postgres会创建一个完整的SQL查询,包括所有的语法和语义检查、计划计算等,以识别和更新记录,还是告诉postgres,它可以使用指针指向光标指出的数据来更新其中的一个字段?@arthur:这次更新没有涉及指针。它是动态SQL,必须计划和执行。如果不是动态的,查询计划将被保存和重用。由于Postgres 9.2,查询规划师在决定是否重用时尽量明智……非常感谢您的回答,尽管我无法更新引用光标指向的字段有点令人沮丧。现在,我只是返回整个更新的表,作为用更新的表替换原始表的函数的答案。这一定比用个人更新查询轰炸postgres要快,你觉得呢?不幸的是,我不能用集合来表示更新,因为tp_id只能在表的顺序扫描期间计算:-感谢SQLFIDLE!!完全帮我弄清楚我错过了什么。