我想知道Oracle在子查询以及update和delete子句的执行方面的行为是什么。
我想知道Oracle:
修改
使用的数据库:Oracle 11.2.0.3.0 我有这个漂亮的查询
DROP TABLE T1; DROP TABLE IT1; DROP TABLE OT1; CREATE TABLE T1 ( ID INTEGER, V INTEGER, PIVOT INTEGER ); CREATE TABLE IT1 ( ID INTEGER ); CREATE TABLE OT1 ( ID INTEGER, FOO INTEGER, NV INTEGER ); INSERT INTO T1 (ID,V,PIVOT) VALUES (1,1,1); INSERT INTO T1 (ID,V,PIVOT) VALUES (2,1,1); INSERT INTO IT1 (ID) VALUES (1); INSERT INTO IT1 (ID) VALUES (2); INSERT INTO OT1 (ID,NV,FOO) VALUES (1,2,0); INSERT INTO OT1 (ID,NV,FOO) VALUES (2,2,0); commit; MERGE INTO T1 TARGET USING ( SELECT DISTINCT T1.ID,T1.V, OT1.NV FROM T1 INNER JOIN IT1 ON T1.ID = IT1.ID LEFT OUTER JOIN OT1 ON OT1.ID = IT1.ID WHERE T1.PIVOT = 1 or OT1.FOO=40) SRC ON (SRC.ID = TARGET.ID) WHEN MATCHED THEN UPDATE SET TARGET.V=SRC.NV DELETE WHERE TARGET.V=SRC.V; commit;
如果某个项目有新版本,则该项目将使用新版本(UPDATE子句)进行更新。如果不是,则销毁该项(DELETE子句)。删除不应该发生
此声明不符合我的预期。它删除所有链接。就像delete子句用修改后的数据执行子查询一样。
注意OT1.FOO = 40这里没用,但似乎造成了问题。如果我向子查询添加order by
(无论顺序标准如何),语句都能正常工作。
谢谢,
尼古拉斯
答案 0 :(得分:1)
SQL标准保证了三个阶段:
这意味着所有“子查询”在第一次写入发生之前逻辑执行。这可以使用不同的物理计划形状来实现,但这与您的应用程序逻辑无关。
答案 1 :(得分:0)
忘了回答这个问题。
该问题已知,应通过补丁11。2。4。4(2013年第4季度发布)修复。
Oracle建议采用以下临时解决方法:
alter session set "_complex_view_merging"=false;"
或提示NO_MERGE
答案 2 :(得分:-1)
我不相信Oracle会保证像这样的复合语句的操作顺序。我希望生成的解释计划将显示操作的确切顺序。我过去曾使用TOAD解析/调整这样的查询。