使用with子句更新语句

时间:2011-03-21 16:27:51

标签: sql oracle

我有一个脚本使用一堆with子句来得出一些结果,然后我想把这个结果写在一个表中。我无法理解它,有人能指出我正确的方向吗?

这是一个简化的例子,表明了我想做的事情:

with comp as (
  select *, 42 as ComputedValue from mytable where id = 1
)
update  t
set     SomeColumn = c.ComputedValue
from    mytable t
        inner join comp c on t.id = c.id 

真实的东西有很多with子句都互相引用,所以实际使用with子句的任何建议都比将其重构为嵌套子查询更受欢迎。

提前致谢,

格特 - 扬

3 个答案:

答案 0 :(得分:43)

如果有人跟我来这里,这个答案对我有用。

update mytable t
set z = (
  with comp as (
    select b.*, 42 as computed 
    from mytable t 
    where bs_id = 1
  )
  select c.computed
  from  comp c
  where c.id = t.id
)
祝你好运,

GJ

答案 1 :(得分:27)

WITH语法似乎在内联视图中有效,例如

UPDATE (WITH comp AS ...
        SELECT SomeColumn, ComputedValue FROM t INNER JOIN comp ...)
   SET SomeColumn=ComputedValue;

但在快速测试中,我总是以ORA-01732: data manipulation operation not legal on this view失败,尽管如果我重新编写以消除WITH子句,它会成功。因此,重构可能会干扰Oracle保证密钥保存的能力。

但是你应该可以使用MERGE。使用您发布的简单示例甚至不需要WITH子句:

MERGE INTO mytable t
USING (select *, 42 as ComputedValue from mytable where id = 1) comp
ON (t.id = comp.id)
WHEN MATCHED THEN UPDATE SET SomeColumn=ComputedValue;

但是我知道你有一个更复杂的子查询要分解。我认为您可以使USING子句中的子查询任意复杂,并包含多个WITH子句。

答案 2 :(得分:1)

您始终可以执行以下操作:

update  mytable t
set     SomeColumn = c.ComputedValue
from    (select *, 42 as ComputedValue from mytable where id = 1) c
where t.id = c.id 

您现在也可以在update内使用with语句

update  mytable t
set     SomeColumn = c.ComputedValue
from    (with abc as (select *, 43 as ComputedValue_new from mytable where id = 1
         select *, 42 as ComputedValue, abc.ComputedValue_new  from mytable n1
           inner join abc on n1.id=abc.id) c
where t.id = c.id