2015-06-23 73 views
2

使用单个更新语句两个因列我已经创建该表:更新Oracle中

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旧的价值,这是空的,而非更新的:

Update Vars set B=A*A, C=B+10; 

任何一个可以帮助我的方式,让C要依据的更新值计算使用单个更新语句。

预先感谢您。

+1

你可以写“更新乏集B = A * A,C =(A * A)+ 10; – DirkNM

+0

实际上,列的实际计算太复杂(我张贴在这里只是举例)另外,我的表格有10列,每列都根据一组以前更新的列进行更新。 – TeeKea

+0

@TeeKea您是否使用plsql?以这种方式更好地将其编写为plsql块 – Moudiz

回答

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优化器令人印象深刻......它真的很可怕。

+0

嗯,我看到你在那里做什么,但是这可能会变得非常粗糙,十列将根据彼此的值进行更新。 –

+0

是的!这是丑陋的...但高效。 PL/SQL会更漂亮,但效率更低(因为更新可以自动并行化并且PL/SQL块不能)...但它只会有点粗糙;-)。我测试了超过10000个子查询(1个选择10000个子选择)的真正粗糙的查询,我的小Oracle实例可以毫无问题地解决它。 – acesargl

+0

感谢@acesargl,感谢您的有益答案,无论其适用于我的十列的复杂性如何。 – TeeKea

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来测试将要设置的值。

你甚至可能有嵌套的内嵌视图...

select 
    v.*, 
    new_b + 10 new_c 
from (
    select 
    *, 
    a * a new_b 
    from 
    vars) v 
+0

对不起,但我无法执行这种查询:“select *,a from vars”。 我得到这个错误:“ORA-00923从关键字找不到预期的地方”。 – TeeKea