我不经常与Oracle合作,尽管偶尔我会为之着迷。最近,我遇到了以下情况,并试图弄清这一点。
试图遵循有关Merge statement from Oracle's SQL Language Reference的文档,我在下面创建了MERGE INTO语句。它可以编译,但不能正常工作。 当ON( tbl.field_name = S.field_name )评估为False 时,逻辑不会流入(未匹配时)部分
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
答案 0 :(得分:1)
在table_name.field_name
中找不到“ 12345”时,在第一种情况下,您使用没有行的表。控件确实会流到when not matched then insert...
分支(不确定为什么会这样),但是没有任何要插入的内容,因为S
为空。在第二个示例中,即使未找到该值,您也将使用表dual
,该表确实具有一行。无论您没有与我们共享什么代码部分,您都应该绝对希望与两个不同的MERGE语句具有不同的行为。
答案 1 :(得分:1)
我认为您正在错误地查看源表和目标表之间的比较。
合并最初基于源表中的数据,然后然后在目标表中是否存在匹配的数据。您似乎希望它能以其他方式起作用。
使用:
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
行或其dummy
列-并且目标表中可能有也可能没有匹配的记录,因此它进入了预期的分支。源表中的结果集不能为空,因为它现在为dual
,不能为空。
无论哪种方式,至少您的不匹配子句似乎都没有使用S
中的数据,通常是这种情况-否则dual
版本也可以使用。