art*_*hur 6 postgresql dynamic-sql plpgsql cursor sql-update
我正在调整一些PL/pgSQL代码,所以我refcursor可以将表名作为参数.因此我更改了以下行:
declare
pointCurs CURSOR FOR SELECT * from tableName for update;
Run Code Online (Sandbox Code Playgroud)
这一个:
OPEN pointCurs FOR execute 'SELECT * FROM ' || quote_ident(tableName) for update;
Run Code Online (Sandbox Code Playgroud)
我调整了循环,然后,循环经过了.现在在循环中的某个时刻我需要更新记录(由光标指向)并且我卡住了.我该如何正确调整以下代码行?
UPDATE tableName set tp_id = pos where current of pointCurs;
Run Code Online (Sandbox Code Playgroud)
我修改了tableName和的引号,并在开头pos添加了EXECUTE子句,但是我得到了错误where current of pointCurs.
(i)我如何更新记录?
(ii)该函数适用于来自公共模式的表,而来自其他模式的表(例如trace.myname)失败.
任何评论都非常感谢..
Erw*_*ter 15
EXECUTE不是"子句",而是执行SQL字符串的PL/pgSQL命令.在命令中看不到游标.您需要将值传递给它.
因此,您无法使用特殊语法WHERE CURRENT OFcursor.我使用系统列ctid来确定行而不知道唯一列的名称.请注意,ctid只保证在同一事务中保持稳定.
CREATE OR REPLACE FUNCTION f_curs1(_tbl text)
RETURNS void AS
$func$
DECLARE
_curs refcursor;
rec record;
BEGIN
OPEN _curs FOR EXECUTE 'SELECT * FROM ' || quote_ident(_tbl) FOR UPDATE;
LOOP
FETCH NEXT FROM _curs INTO rec;
EXIT WHEN rec IS NULL;
RAISE NOTICE '%', rec.tbl_id;
EXECUTE format('UPDATE %I SET tbl_id = tbl_id + 10 WHERE ctid = $1', _tbl)
USING rec.ctid;
END LOOP;
END
$func$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
FOR循环游标的语句也有一个变体,但它只适用于绑定游标.我们必须在这里使用未绑定的游标.
FOR循环中的隐式游标有通常没有必要在PLPGSQL明确的游标.使用FOR循环的隐式游标代替:
CREATE OR REPLACE FUNCTION f_curs2(_tbl text)
RETURNS void AS
$func$
DECLARE
_ctid tid;
BEGIN
FOR _ctid IN EXECUTE 'SELECT ctid FROM ' || quote_ident(_tbl) FOR UPDATE
LOOP
EXECUTE format('UPDATE %I SET tbl_id = tbl_id + 100 WHERE ctid = $1', _tbl)
USING _ctid;
END LOOP;
END
$func$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
或者更好,但是(如果可能的话):在基于集合的操作方面重新思考您的问题并执行单个(动态)SQL命令:
-- Set-base dynamic SQL
CREATE OR REPLACE FUNCTION f_nocurs(_tbl text)
RETURNS void AS
$func$
BEGIN
EXECUTE format('UPDATE %I SET tbl_id = tbl_id + 1000', _tbl);
-- add WHERE clause as needed
END
$func$ LANGUAGE plpgsql;
Run Code Online (Sandbox Code Playgroud)
SQL Fiddle演示了所有3种变体.
模式限定的表名trace.myname实际上由两个标识符组成.你必须
regclass类型:CREATE OR REPLACE FUNCTION f_nocurs(_tbl regclass)
RETURNS void AS
$func$
BEGIN
EXECUTE format('UPDATE %s SET tbl_id = tbl_id + 1000', _tbl);
END
$func$ LANGUAGE plpgsql;Run Code Online (Sandbox Code Playgroud)
我切换%I到%s,因为regclass参数在(自动)转换为时自动正确转义text.
这个相关答案的更多细节:
| 归档时间: |
|
| 查看次数: |
10295 次 |
| 最近记录: |