我有一个查询,用于更新新列的所有过去历史记录。它从具有相应ID的源表中提取值。它还将更新时间与当前时间进行比较,当前时间可能会发生变化但现在保证会在每一行上运行。
UPDATE table1
SET table1.comment =
(SELECT table2.comment
FROM table2
WHERE table1.ID = table2.ID)
WHERE(SELECT table2.updateTime
FROM table2
WHERE table1.ID = table2.ID) < sysdate
生产中有数百万行,我需要将其限制在循环中,或者只需要一次更新这么多行。我对SQL很新,并且无法找到有关循环如何限制更新行数的任何文档。循环如何知道正在使用的表中的行?
答案 0 :(得分:0)
有几件事......首先,如果你的表有主键,那么这可能是首选的更新方法:
update (
select
t1.comment c1, t2.comment c2
from
table1 t1,
table2 t2
where
t1.id = t2.id and
t2.updateTime < sysdate
)
set
c1 = c2
其次,假设updateTime意味着我认为它意味着什么,它不会总是小于sysdate吗?是否有理由这样做?
第三,为了尽量减少不必要的更新,我想你可以添加这个。假设只有一部分行需要更新,这应该会极大地影响性能。
update (
select
t1.comment c1, t2.comment c2
from
table1 t1,
table2 t2
where
t1.id = t2.id and
t2.updateTime < sysdate and
((t1.comment is null and t2.comment is not null) or
(t1.comment is not null and t2.comment is null) or
t1.comment != t2.comment)
)
set
c1 = c2
最后,我并不是说Loop永远不会有所帮助,但我说这通常是错误的做法。 Oracle已经过调整以做这种事情。如果您的更新查询速度很慢,那么在程序循环中包装它会让它运行得更快。对于经过良好调整的Oracle数据库,更新数百万行不应该是一个问题。
我理解这样做背后的想法,这在人类世界中是有意义的。我自己尝试过只是为了让一个聪明的甲骨文男人告诉我我错了。当他调整更新查询时,结果证明他是对的。