【问题标题】:What is the execution order of Oracle MERGE INTO clauses with a subquery带有子查询的Oracle MERGE INTO 子句的执行顺序是什么
【发布时间】:2013-08-14 00:33:00
【问题描述】:

我想知道 Oracle 在子查询和更新和删除子句的执行方面的行为是什么。

不知甲骨文:

  1. 执行子查询并为每一行执行更新和删除子句
  2. 执行更新的子查询,然后执行删除的子查询
  3. 1) 和 2),优化器选择最佳策略
  4. 其他?

编辑:

使用的数据库:Oracle 11.2.0.3.0 我有这个漂亮的查询

删除表 T1; 删除表 IT1; 删除表 OT1; 创建表 T1 ( ID 整数, V 整数, 枢轴整数 ); 创建表 IT1 ( ID 整数 ); 创建表 OT1 ( ID 整数, 整数, NV 整数 ); 插入 T1 (ID,V,PIVOT) 值 (1,1,1); 插入 T1 (ID,V,PIVOT) 值 (2,1,1); 插入 IT1 (ID) 值 (1); 插入 IT1 (ID) 值 (2); 插入 OT1 (ID,NV,FOO) 值 (1,2,0); 插入 OT1 (ID,NV,FOO) 值 (2,2,0); 犯罪; 合并到 T1 目标使用 ( 选择不同的 T1.ID、T1.V、OT1.NV 从 T1 T1.ID 上的内部连接 ​​IT1 = IT1.ID OT1.ID 上的左外连接 OT1 = IT1.ID 其中 T1.PIVOT = 1 或 OT1.FOO=40) SRC 开(SRC.ID = 目标.ID) 当匹配然后 更新集 TARGET.V=SRC.NV 删除目标.V=SRC.V; 犯罪;

如果某个项目有新版本,则该项目将使用新版本进行更新(UPDATE 子句)。如果不是,则该项目被销毁(DELETE 子句)。删除不应该发生

这个语句不像我预期的那样工作。它会删除所有链接。就像删除子句使用修改后的数据执行子查询一样。

注意 OT1.FOO=40 在这里没用但似乎造成了问题。如果我将order by 添加到子查询(无论顺序标准如何),则该语句将正常工作。

谢谢,

尼古拉斯

【问题讨论】:

标签: sql oracle


【解决方案1】:

SQL 标准保证三个阶段:

  1. 为所有正在更新的行计算新值(只读阶段)
  2. 一次性应用所有更改
  3. 约束已验证

这意味着所有“子查询”在第一次写入发生之前逻辑执行。这可以使用不同的物理计划形状来实现,但这与您的应用程序逻辑无关。

【讨论】:

  • 如果我理解正确,即使有更新或删除,子查询也总是返回相同的数据?
  • 是的,它必须像操作数据库快照一样操作。
  • 我不明白我的问题。我已经通过了查询,希望它会有所帮助
  • 可能Oracle没有遵守标准的这条规则。这是一个重要的特性,如果发现它在 Oracle 中不存在,我会感到有点震惊。子查询中的 order-by 在语义上也没有意义,因为没有 top 子句。这应该被忽略或导致错误。反正我的知识还不足以解决你的问题。
【解决方案2】:

忘记回答这个问题了。

这个问题是已知的,应该通过补丁 11.2.0.4(2013 年第四季度发布)修复。

Oracle 建议以下临时解决方法:

alter session set "_complex_view_merging"=false;"  

或者提示NO_MERGE

【讨论】:

    【解决方案3】:

    我不相信 Oracle 保证这样的复合语句的操作顺序。我希望生成的解释计划将显示操作的确切顺序。我过去曾使用 TOAD 来剖析/调整这样的查询。

    【讨论】:

    • 如果无法保证订单,解释计划也无济于事,因为它可能随时更改。
    猜你喜欢
    • 2021-07-31
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 2014-07-30
    • 2015-11-24
    • 1970-01-01
    • 1970-01-01
    • 2011-01-16
    相关资源
    最近更新 更多