【问题标题】:Update statement using with clause使用 with 子句更新语句
【发布时间】:2011-03-21 16:27:50
【问题描述】:

我有一个脚本,它使用一堆 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 子句的建议都比将其重构为嵌套子查询更受欢迎。

提前致谢,

格特-简

【问题讨论】:

  • 仅供参考:您不必编辑标题和问题来指出您自己回答了。只需将您的解决方案添加为自己的答案,如果它是最好的,请选择它。
  • 好的,还不能将其标记为已回答。谢谢!
  • 我也在搜索回复,我在这里找到了它:stackoverflow.com/questions/7030699/…

标签: sql oracle


【解决方案1】:

如果有人在我之后来到这里,这就是对我有用的答案。

注意:请在使用前阅读 cmets,这不完整。 我能给出的关于更新查询的最佳建议是切换到 SqlServer ;)

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

【讨论】:

  • 这不会更新所有行吗?如果有 c.id t.id 的行,它们不会被设置为 null 吗?有谁知道把 where 子句放在外面的方法吗?
  • 不要再使用Oracle了,这已经是很久以前的事了。试试看,让我们知道 ;-) IIRC 这对我有用。
  • @gjvdkamp 它就像 Sanjay Nambiar 所说的那样工作:更新适用于选定的行,但所有其他不在“where”的行都设置为 null。 [2] 有没有人知道将 where 子句也放在外面的方法?
  • @robsonrosa - 要仅更新匹配的行,您基本上只需将子选择从 SET 子句复制到 WHERE EXISTS 子句中
  • 就像@SanjayNambiar 所说的那样,我认为这需要以某种方式恢复,因为这不是答案,否则会导致人们不阅读 cmets 的问题
【解决方案2】:

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 子句。

【讨论】:

  • 嗨,非常感谢您的努力,已经设法让它运行。我使用的 with 语句有相当多的级别来计算平均值和标准差,然后使用没有标准化(统计)来自其他表等的数据将是重构的真正痛苦。该示例只是更新语法。
【解决方案3】:

你总是可以这样做:

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 

【讨论】:

  • UPDATE ... SET ... FROM 在 Oracle 中不是有效的语法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-04-21
  • 2018-10-26
  • 2013-03-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-07
相关资源
最近更新 更多