【问题标题】:How to update multiple rows include with-select sentence in Oracle如何在Oracle中更新多行包括with-select语句
【发布时间】:2016-01-18 14:24:00
【问题描述】:

我想用另一个表中的值更新 table_a 的 col1。

我做了一个选择

with tmp as (
 blar~
)
select col1 from table_b b, tmp t
where 1=1
and b.col2 = t.col_x

更新加入条件

 table_a.col3 = table_b.col3

【问题讨论】:

    标签: oracle select sql-update multiple-columns


    【解决方案1】:

    原理是像这样创建一个可更新的视图:

    update 
        ( with tmp as ( select col2 
                        from table_c)
        select a.col1 as a_col1
               , b.col1 as b_col1
               , a.id as a_id
        from tmp
             join table_b b
                 on b.col2 = tmp.col2
             join table_a a
                 on a.col3 = b.col3
         ) t
    set a_col1 = b_col1
    /
    

    重点是:

    1. 我们只更新视图中的一个表;
    2. 视图中的所有其他表都有主键或唯一键,因此它们保证只返回一行。
    3. 必须在视图中引用唯一列

    如果更新不满足这些限制,它将抛出ORA-01779: cannot modify a column which maps to a non key-preserved table

    尚不清楚为什么要使用 WITH 子句,但这可能会使您更难确保您使用的是保留键的表。例如,上述查询的这个变体失败,即使我们知道 DUAL 总是返回一行。

    update 
        ( with tmp as ( select c.col2 
                        from table_c c
                              join dual d
                              on d.dummy = c.col2)
        select a.col1 as a_col1
               , b.col1 as b_col1
               , a.id as a_id
        from tmp
             join table_b b
                 on b.col2 = tmp.col2
             join table_a a
                 on a.col3 = b.col3
         ) t
    set a_col1 = b_col1
    /
    

    如果此解释不能帮助您找到解决方案,请编辑您的问题以提供更多详细信息。包括您收到的任何错误消息。 “我无法成功”不足以让我们帮助您。


    “我用的是你的答案,叫 /*+ bypass_ujvc */”

    这是一个未记录的提示,因此在生产环境中使用它非常冒险。此外,似乎Oracle removed it in 11gR2 和更高版本,所以它不会有任何影响(这就是为什么使用未记录的提示是有风险的)。您应该找到一个无需提示即可工作的解决方案。

    【讨论】:

    • 谢谢!我使用了您的答案,该答案称为 /*+ bypass_ujvc */ 并且 b_col1 被设置为键值。感谢@APC!有一个美好的每一天!
    【解决方案2】:

    由于您没有提供足够的信息,因此很难提供帮助。但是结果可以通过以下方式更新:

    update  (
      with temp as (
                    select col1 from table_a 
                    )
       select col1 from temp )
    set col1 = 'newValue'
    

    【讨论】:

    • 谢谢,但我无法成功。这个我会多尝试的~
    猜你喜欢
    • 2019-08-24
    • 2014-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-06
    • 1970-01-01
    相关资源
    最近更新 更多