我并不定期与 Oracle 合作,但偶尔也会被机会所吸引。最近我遇到了以下情况,并试图理解这一点。
尝试遵循有关 Merge statement from Oracle's SQL Language Reference 的文档我在下面创建了 MERGE INTO 语句。它可以编译但无法正常工作。 当 ON (tbl.field_name = S.field_name) 评估为 False 时,逻辑不会流向(WHEN NOT MATCHED) 部分
MERGE INTO table_name tbl
USING (SELECT field_name FROM table_name WHERE field_name = '12345') S
ON (tbl.field_name = S.field_name)
WHEN MATCHED THEN UPDATE . . .
-- flow arrives here when expected, this works correctly
WHEN NOT MATCHED THEN INSERT . . .
-- When a match against (field_name) doesn't exist **flow never comes here?
下面的 MERGE INTO 语句工作正常,但我不明白为什么它工作正常。一位现已被隔离的同事帮助了我,然后没有任何解释就离开了。她只更改了 USING 和 ON 子句。我试图理解其中的(USING Dual)部分如何使其正常工作? 或者为什么使用 USING 子句(在上面的示例中)使用显式 SELECT)无法按预期工作?任何人都可以帮助我解决这个问题吗?
MERGE INTO table_name tbl
USING dual
ON (tbl.field_name = '12345')
WHEN MATCHED THEN UPDATE . . .
-- flow arrives here when expected, this works correctly
WHEN NOT MATCHED THEN INSERT . . .
-- When a match against (field_name) doesn't exist **flow arrives here correctly
最佳答案
我认为您以错误的方式查看源表和目标表之间的比较。
合并首先基于源表中的数据,然后目标表中是否有匹配的数据。您似乎期望它以相反的方式工作。
与:
USING (SELECT field_name FROM table_name WHERE field_name = '12345') S
ON (tbl.field_name = S.field_name)
如果源表中有一行具有该值,则S
只有一行(假设它是唯一的),并且目标表中可能有也可能没有匹配的行;它将按预期进入匹配或不匹配的子句,具体取决于目标表中的内容,但仅使用所选源行中的值。
但是,如果源表中没有具有该值的行,则 S
是一个空结果集,因此 ON
子句无事可做,所以它是从未真正评估过 - 在这种情况下,它不会达到不匹配的子句。没有什么可以比较,并且“没有”不匹配或与其他任何东西都不匹配。
而:
USING dual
ON (tbl.field_name = '12345')
dual
中始终只有一行,因此始终会评估 ON
子句 - 尽管它实际上并不使用该 dual
行或其虚拟列 - 目标表中可能有也可能没有匹配的记录,因此它会进入预期的分支。源表中不能有空结果集,因为它现在是dual
,不能为空。
无论哪种方式,您的不匹配子句至少都没有使用来自 S
的数据,通常情况就是这样 - 否则 dual
版本将工作也可以。
关于sql - Oracle Merge Into 的Using 子句?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54813090/