Sql Oracle合并到的Using子句?

Sql Oracle合并到的Using子句?,sql,oracle,plsql,Sql,Oracle,Plsql,我不经常与甲骨文合作,但偶尔也会被机会迷住。最近我遇到了下面的情况,我正在努力理解这一点 我在下面创建了MERGE-INTO语句,试图遵循有关该语句的文档。它可以编译,但不能正常工作。当ON tbl.field_name=S.field_name计算为False时,逻辑不会流到When not MATCHED部分 下面的MERGE-INTO语句工作正常,但我不理解它为什么工作正常。一位同事,现在被隔离了,帮我解决了这个问题,然后没有解释就离开了。她只修改了USING和ON子句。我试图理解如何使用

我不经常与甲骨文合作,但偶尔也会被机会迷住。最近我遇到了下面的情况,我正在努力理解这一点

我在下面创建了MERGE-INTO语句,试图遵循有关该语句的文档。它可以编译,但不能正常工作。当ON tbl.field_name=S.field_name计算为False时,逻辑不会流到When not MATCHED部分

下面的MERGE-INTO语句工作正常,但我不理解它为什么工作正常。一位同事,现在被隔离了,帮我解决了这个问题,然后没有解释就离开了。她只修改了USING和ON子句。我试图理解如何使用这个双重部分导致它正常工作?或者为什么上面示例中带有显式SELECT的USING子句不能按预期工作?有人能帮我吗

    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

如果在表_name.field _name中找不到“12345”,则在第一种情况下,您使用的是没有行的表。控件在不匹配时流向,然后插入。。。分支不确定为什么您认为它不存在,但由于S是空的,所以没有什么可插入的。在第二个示例中,即使找不到该值,也将使用表dual,它只有一行。不管您没有与我们共享的代码部分中有什么内容,您绝对应该期望两个不同的合并语句有不同的行为。

我认为您在错误地看待源表和目标表之间的比较

合并最初基于源表中的数据,然后基于目标表中是否有匹配的数据。你似乎希望它能反过来工作

与:

如果源表中有一行具有该值,则S有一行,假设该行是唯一的,并且目标表中可能有匹配行,也可能没有匹配行;它将根据目标表中的内容按预期进入匹配子句或不匹配子句,但仅使用所选源行中的值

但是,如果源表中没有具有该值的行,那么S是一个空结果集,因此ON子句不需要执行任何操作,因此它永远不会进行真正的计算——在这种情况下,它不会到达not matched子句。没有什么可以比较,“没有”与其他任何东西都不匹配或不匹配

鉴于:

     USING dual
     ON (tbl.field_name = '12345')
dual中始终只有一行,因此始终对ON子句进行求值—尽管它实际上没有使用该dual行或其伪列—并且目标表中可能有也可能没有匹配的记录,因此它进入预期的分支。源表中不能有空的结果集,因为它现在是dual,不能为空


不管是哪种情况,至少您的not matched子句似乎没有使用来自S的数据,这通常是这样的-否则双版本也会起作用。

我认为这会有所帮助。我听上去像是在正确的轨道上吗?在我的第一个case/top-most示例中,如果没有记录,其中table_name.field_name='12345',那么S将没有行,并且可能MERGE没有无行的case,并且匹配或不匹配时都不会运行?这听起来对吗?谢谢你的帮助。如果我理解正确的话,当Using子句在子句上没有返回任何行,并且下面的所有内容都不会被计算?本质上,当Using子句不返回行时,合并逻辑退出或停止执行。在我的第一个例子的用法中,你是这样看的吗。ON子句和matched/not matched子句只对USING结果集中的行进行求值。在这种情况下,没有行,因此它们根本不会被计算,是的。可能还有其他场景,其中该结果集中有多行,但仍然只有这些行被计算。它永远无法计算源中不存在的行。零行只是一个极端情况,逻辑是一样的。
     USING (SELECT field_name FROM table_name WHERE field_name = '12345') S
     ON (tbl.field_name = S.field_name)
     USING dual
     ON (tbl.field_name = '12345')