我必须将oracle db中的表更新为10k批处理。
我尝试了这个:
BEGIN WHILE (true) LOOP UPDATE TOP (10000) CUSTOMERS SET ACTIVE = 'N' WHERE ACTIVE='Y'; IF sql%notfound THEN EXIT; END IF; COMMIT; END LOOP; END;
它不起作用,因为plsql不支持top。
有什么建议?
使用JVA的建议,您的pl / SQL块应按以下方式完成(因为您是pl / sql的新手,所以我添加了一些您可能感兴趣的语法建议):
BEGIN -- WHILE (TRUE) can be omitted: "loop ... end loop;" -- already is an endless loop LOOP UPDATE CUSTOMERS SET ACTIVE = 'N' WHERE ACTIVE='Y' AND rownum <= 1000; exit when sql%notfound; -- notice that exit accepts "when condition" --IF sql%notfound THEN -- you can avoid a if/endif by using "exit when" -- EXIT; -- END IF; COMMIT; END LOOP; commit; -- you missed this commit for the last iteration END;
不要试图将“ commit”放在“ sql%notfound退出时”之前:在“ commit” sql%notfound之后总是错误的,您的循环将是无休止的。
让我指出,为了提高效率,此方法需要对“ ACTIVE”列进行索引!
如果您在“活动”列上没有索引,则每次“更新”都将被迫从头开始重新启动全表扫描,以查找仍需要更新的下1000条记录。
我提议的另一种方法使用了一些高级PL / SQL功能,作为学习者,您对mighy感兴趣(rowid,“ table of”,光标批量获取和“ forall”),并且只对要更新的表进行了一次扫描因此(在没有索引的情况下)它的性能比以前的方法要好。请记住,如果您有索引,这会比较慢 (但是使用foralls,批量收集和rowid访问不会那么慢) ,但是在事情更复杂的情况下(例如:当where条件时 ) 会派上用场需要使用无法提高速度的复杂联接访问其他表中的数据)。在某些情况下,“ where”是如此复杂且缓慢,以至于您真的不想使用“ where rownum <= 1000”方法一遍又一遍地重新执行它。
declare type rowid_array is table of rowid; ids rowid_array; cursor cur is select rowid as id from CUSTOMERS where ACTIVE='Y'; begin open cur; loop fetch cur bulk collect into ids limit 1000; exit when ids.count = 0; forall c in ids.first .. ids.last update CUSTOMERS set ACTIVE='N'; commit; end loop; end;