sql - Oracle Merge Into 的Using 子句?

标签 sql oracle plsql

我并不定期与 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/

相关文章:

sql - HSQLDB 2.2.9 运行脚本+SqlFile

oracle - Oracle PL/SQL 中的 RTRIM(CLOB 字段)

sql - Oracle SQL 按单个字段分组并计算分组的行数

oracle - 第 4 行错误 : PL/SQL: SQL Statement ignored

sql - 临时中间表

oracle - PL/SQL : Any trick to avoid cloning of objects?

sql - Firebird 多重声明

MySQL Select INTO csv 文件分隔符工作不正确

MySQL,如何获取行之间的时间差

Oracle 日期比较问题完全困惑 - 我做错了什么?