使用with子句更新语句

问题描述 投票:0回答:4

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

sql oracle-database
4个回答
65
投票

如果有人追随我来到这里,这就是对我有用的答案。

注意:请在使用前阅读评论,这并不完整。 我可以给出的更新查询的最佳建议是切换到 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


43
投票

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 保证密钥保存的能力。

不过,您应该能够使用合并。 使用您发布的简单示例,这甚至不需要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
子句。


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 

0
投票

大多数时候,我更喜欢“With”声明,但我不知道如何应用它,如果可能的话。因此,我决定将相同的知识应用于我“创建”的表(我相信它指的是内联视图)。尝试以下方法:

当我尝试更新多个项目的多个值并使用 case 语句将字段的特定值从一个表应用到另一个表时,这对我来说非常有用。

update  (  select    i.item_id,
                     i.item_name,
                     i.nmfc_code,
                     i.dim_uom_id,
                     w.f_class
            from   item i
            left join
                   warehouse w on
                   i.item_id = w.item_id
        )
set     dim_uom_id = 4,
        nmfc_code = case f_class
                        when '50'   then 1
                        when '92.5' then 2
                        when '125'  then 3
                        when '150'  then 4
                    end
where
        item_id   in    (   select  item_id
                            from    item
                            where   item_name in (
                                                     'i1',
                                                     'i2',
                                                     'i3',
                                                     'i4',
                                                     'i5'
                                                 )
                        )
© www.soinside.com 2019 - 2024. All rights reserved.