Oracle合并到Using子句?

时间:2019-02-21 17:36:32

标签: sql oracle plsql

我不经常与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

2 个答案:

答案 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版本也可以使用。