我创建了这个表:
Create table Vars(A number, B number, C number);
然后,我插入了一个新行,其中只有第一列(即A
)具有值:
Insert Into Vars(A) values (2);
现在,我想创建一个更新语句,修改列B
和C
的值,如下所示:
B = A * A
C = B + 10
问题在于,当我执行以下更新语句时,B
的值会正确更新,但C
的值会根据B
的旧值更新,这是null,而不是更新的:
Update Vars set B=A*A, C=B+10;
任何人都可以通过一种方式帮助我,使用单个更新语句,根据C
的更新值计算B
。
提前谢谢。
答案 0 :(得分:2)
使用一系列嵌套子查询以正确的顺序计算表达式。每个内部选择都会在外部列之前对列进行转换。
第一个子查询(内部)将在列列表中包含ROWID,最后一个(外部)将使用UPDATE ROWID绑定内部ROWID。每个中间子查询必须包括其计算,外部子查询所需的列以及第一个子查询生成的ROWID。
UPDATE VARS V
SET (B,C) =
(SELECT B, B+10 AS C
FROM (SELECT A*A AS B, ROWID AS X FROM VARS)
WHERE V.ROWID = X
);
不要担心嵌套子查询的性能。无论你有多少级别的子查询,oracle都只执行1次全表访问(更新)和1次基于rowid的访问(子查询)。完全访问是由于您的UPDATE中缺少WHERE。
我在11gR2上测试过它。 Oracle优化器令人印象深刻......真的很可怕。
答案 1 :(得分:0)
如果必须这样做,可以考虑的一个选项是更新内联视图。
如果您可以定义以下表单的查询:
select *,
a * a new_b,
(a * a) + 10 new_c
from vars
...那么你也可以......
update (
select *,
a * a new_b,
(a * a) + 10 new_c
from vars)
set b = new_b,
c = new_c
这也使逻辑非常可测试,因为您可以将内联视图作为选项来运行,以测试将要设置的值。
你甚至可能有嵌套的内嵌视图......
select
v.*,
new_b + 10 new_c
from (
select
*,
a * a new_b
from
vars) v