我正在尝试使用Postgres每1000行更新一次特定记录。我正在寻找一种更好的方法。我的功能描述如下:
CREATE OR REPLACE FUNCTION update_row()
RETURNS void AS
$BODY$
declare
myUID integer;
nRow integer;
maxUid integer;
BEGIN
nRow:=1000;
select max(uid_atm_inp) from tab into maxUid where field1 = '1240200';
loop
if (nRow > 1000 and nRow < maxUid) then
select uid from tab into myUID where field1 = '1240200' and uid >= nRow limit 1;
update tab
set field = 'xxx'
where field1 = '1240200' and uid = myUID;
nRow:=nRow+1000;
end if;
end loop;
END; $BODY$
LANGUAGE plpgsql VOLATILE
如何改善此程序?我认为出了点问题。循环不会结束并且需要太多时间。
答案 0 :(得分:2)
要在SQL中执行此任务,可以使用row_number
窗口函数并仅更新数字可被1000整除的那些行。
您的循环未完成,因为其中没有EXIT
或RETURN
。
答案 1 :(得分:0)
我怀疑您是否可以在过程循环方面与标准SQL更新的性能相媲美。不必一次做一次,只需将其作为一个单独的语句即可完成:
with t2 as (
select
uid, row_number() over (order by 1) as rn
from tab
where field1 = '1240200'
)
update tab t1
set field = 'xxx'
from t2
where
t1.uid = t2.uid and
mod (t2.rn, 1000) = 0
根据我的评论,我假设您的意思是“每千行”,因为没有指定如何确定什么元组是什么行号。通过更改“排序依据”条件,可以轻松进行修改。
在更新(t1.field1 = '1240200'
)上添加第二个where子句不会造成伤害,但如果这些嵌套子句是嵌套循环,则可能没有必要。
从概念上讲,这可能与Laurenz的想法类似。
答案 2 :(得分:0)
我这样解决了:
declare
myUID integer;
nRow integer;
rowNum integer;
checkrow integer;
myString varchar(272);
cur_check_row cursor for select uid , row_number() over (order by 1) as rn, substr(fieldxx,1,244)
from table where field1 = '1240200' and uid >= 1000 ORDER BY uid;
BEGIN
open cur_check_row;
loop
fetch cur_check_row into myUID, rowNum, myString;
EXIT WHEN NOT FOUND;
select mod(rowNum, 1000) into checkrow;
if checkrow = 0 then
update table
set fieldxx= myString||'O'
where uid in (myUID);
end if;
end loop;
close cur_check_row;