每1000行更新表

时间:2018-10-24 16:11:58

标签: postgresql stored-procedures

我正在尝试使用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

如何改善此程序?我认为出了点问题。循环不会结束并且需要太多时间。

3 个答案:

答案 0 :(得分:2)

要在SQL中执行此任务,可以使用row_number窗口函数并仅更新数字可被1000整除的那些行。

您的循环未完成,因为其中没有EXITRETURN

答案 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;