使用with子句更新语句

gjv*_*amp 39 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 
Run Code Online (Sandbox Code Playgroud)

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

提前致谢,

格特 - 扬

gjv*_*amp 47

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

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
)
Run Code Online (Sandbox Code Playgroud)

祝好运,

GJ

  • 这不会更新所有行吗?如果有行c.id <> t.id,它们不会被设置为null吗?有没有人知道将where where子句放在外面的方法呢? (5认同)
  • @gjvdkamp就像Sanjay Nambiar说的那样:更新适用于选定的行,但是"where"之外的所有其他行都设置为null.[2]有没有人知道将where where where放在外面的方法? (2认同)
  • @robsonrosa - 要仅更新匹配的行,您基本上只需将 SET 子句中的子选择复制到 WHERE EXISTS 子句中 (2认同)

Dav*_*sta 29

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

UPDATE (WITH comp AS ...
        SELECT SomeColumn, ComputedValue FROM t INNER JOIN comp ...)
   SET SomeColumn=ComputedValue;
Run Code Online (Sandbox Code Playgroud)

但是在快速测试中,我总是失败了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;
Run Code Online (Sandbox Code Playgroud)

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