Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/80.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql oracle11g中的自合并_Sql_Oracle_Merge - Fatal编程技术网

Sql oracle11g中的自合并

Sql oracle11g中的自合并,sql,oracle,merge,Sql,Oracle,Merge,通常情况下,我们需要使用两个不同的查询对同一个表执行更新或插入。我想看看是否可以使用merge语句在表上执行此操作 我只想知道这是否可以做到。否则,我将不得不坚持将查询分离回单独的更新/插入操作 以下是我到目前为止的情况: 方法1: MERGE INTO TABLEA TARGET USING ( SELECT 1 FROM DUAL ) SOURCE ON (TARGET.TARGET.

通常情况下,我们需要使用两个不同的查询对同一个表执行更新或插入。我想看看是否可以使用merge语句在表上执行此操作

我只想知道这是否可以做到。否则,我将不得不坚持将查询分离回单独的更新/插入操作

以下是我到目前为止的情况:

方法1:

          MERGE INTO TABLEA TARGET
          USING (
              SELECT 1 FROM DUAL
          ) SOURCE
          ON (TARGET.TARGET.COLA = '001'
              AND TARGET.TARGET.COLB = '1111111'
              AND TARGET.COLC = '201302'
              )
          WHEN MATCHED THEN
             UPDATE SET TARGET.COLA = '001'
                        ,TARGET.COLB = '1111111'
                        ,TARGET.COLC = '201304'
                        ,TARGET.CREATEDATE = SYSDATE
                        ,TARGET.USERID = 'USERA'
          WHEN NOT MATCHED THEN
             INSERT (TARGET.COLA
                     ,TARGET.COLB
                     ,TARGET.COLC
                     ,TARGET.COLD
                     ,TARGET.CREATEDATE
                     ,TARGET.USERID)
             VALUES('001'
                    ,'1111111'
                    ,'201304'
                    ,'123'
                    ,SYSDATE
                    ,'USERA')
起初,这种方法对我来说很有意义,因为我总是从源代码返回结果,并且会相应地进行更新和插入。然而,甲骨文拒绝这样做:

SQL错误:ORA-38104:无法更新ON子句中引用的列:TARGET.EFF\u FISCAL\u YR\u PD\u NBR 3810400000-无法更新ON子句中引用的列:%s *原因:更新集的LHS包含ON子句中引用的列

方法2:

          MERGE INTO TABLEA TARGET
          USING (
                SELECT ROWID AS RID,COLA,COLB,COLC
                FROM TABLEA
                WHERE COLA = '001'
                      AND COLB = '1111111'
                      AND COLC = '201301'
          ) SOURCE
          ON (TARGET.ROWID = SOURCE.RID)
          WHEN MATCHED THEN
             UPDATE SET TARGET.COLA = '001'
                        ,TARGET.COLB = '1111111'
                        ,TARGET.COLC = '201304'
                        ,TARGET.CREATEDATE = SYSDATE
                        ,TARGET.USERID = 'USERA'
          WHEN NOT MATCHED THEN
             INSERT (TARGET.COLA
                     ,TARGET.COLB
                     ,TARGET.COLC
                     ,TARGET.COLD
                     ,TARGET.CREATEDATE
                     ,TARGET.USERID)
             VALUES('001'
                    ,'1111111'
                    ,'201304'
                    ,'123'
                    ,SYSDATE
                    ,'USERA')
这背后的逻辑是,如果我尝试从源表中查找值,并且它匹配,它将找到记录并用这些值更新自己。但是,如果不匹配,则在尝试插入时会出现问题。因为源是经过筛选的,所以不会返回任何记录,因此目标没有可匹配的内容,也不会插入任何内容。如果在源中没有发现与目标隐式不匹配的记录,我希望这样做是插入,特别是因为insert语句不包含从变量而不是源本身传入的任何by值

我已尝试将源代码更新为如下所示:

                SELECT ROWID AS RID,COLA,COLB,COLC
                FROM TABLEA
                WHERE COLA = '001'
                      AND COLB = '1111111'
                      AND COLC = '201301'
                UNION ALL
                SELECT ROWID,NULL,NULL,NULL FROM DUAL
WHERE ROWNUM <= COUNTOFRETURNEDRESULTS
但问题是合并对匹配的记录进行更新,对不匹配的记录进行插入

对于那些想知道我为什么使用ROWID的人。这是因为并非由我设计的设计表明COLA和COLB将组合成主键,用作表上的索引。不允许复制COLA、COLB和COLC,但它们都可以通过前端接口进行更新。我理解ROWID的缺陷,但因为我只使用一个表作为目标和源,所以无论我对表执行任何CRUD操作,ROWID都将始终与自身匹配


摘要:只有在对匹配项执行更新时,我才使自合并生效,但插入不起作用。

如果我理解正确,COLA、COLB和COLC是TABLEA的复合主键

如果是这种情况,您实际上不需要在这里使用ROWID,只需从dual中选择,然后像第一次尝试那样在ON语句中使用复合键,就可以完成所需的操作

您不需要更新主键列,因此可以在ON子句中使用它们

      MERGE INTO TABLEA TARGET
      USING (
            SELECT '001' COLA,
                   '1111111' COLB,
                   '201301' COLC
            FROM DUAL
      ) SOURCE
      ON (TARGET.COLA = SOURCE.COLA
          AND TARGET.COLB = SOURCE.COLB
          AND TARGET.COLC = SOURCE.COLC
          )
      WHEN MATCHED THEN
         UPDATE SET TARGET.CREATEDATE = SYSDATE
                    ,TARGET.USERID = 'USERA'
      WHEN NOT MATCHED THEN
         INSERT (TARGET.COLA
                 ,TARGET.COLB
                 ,TARGET.COLC
                 ,TARGET.COLD
                 ,TARGET.CREATEDATE
                 ,TARGET.USERID)
         VALUES('001'
                ,'1111111'
                ,'201304'
                ,'123'
                ,SYSDATE
                ,'USERA')

哇,这花了我很长时间

我使用方法3 UNION ALL时走的方向是正确的,它具有来自dual的空记录集

您只需要满足三个条件:

您总是需要从源表返回结果集,但返回的方式与目标不匹配。 不能同时返回匹配集和非匹配集,否则将同时执行插入和更新操作 您的主键是可更新的,因为它在多个列上匹配。我对它们有唯一的约束,所以如果我尝试复制,它将抛出一个错误 因此,源代码应该是这样的:

            SELECT RID,COLA,COLB,COLC FROM
            (
                SELECT ROWID AS RID,COLA,COLB,COLC
                FROM TABLEA
                WHERE COLA = '001'
                    AND COLB = '1111111'
                    AND COLC = '201301'
                UNION ALL
                SELECT ROWID,NULL,NULL,NULL FROM DUAL
                ORDER BY COLA ASC
            ) f
            WHERE ROWNUM <= 1
因此,您返回一条记录。如果满足where子句,则按升序对数据集排序,并仅返回顶部记录集。这样,合并将在此基础上更新。如果不包含ROWNUM的where子句返回零值,它仍将返回null记录集,合并将基于该记录集进行插入

不止一条记录

在我的例子中,如果你真的想得到nutty并得到多条记录,我需要1,那么你必须使用聚合或分析函数获得匹配记录集的计数,并将其填充到变量中,以便where子句标准如下所示:

                SELECT ROWID AS RID,COLA,COLB,COLC
                FROM TABLEA
                WHERE COLA = '001'
                      AND COLB = '1111111'
                      AND COLC = '201301'
                UNION ALL
                SELECT ROWID,NULL,NULL,NULL FROM DUAL
WHERE ROWNUM <= COUNTOFRETURNEDRESULTS
合并到我的目标中 使用从双s中选择1 在t.COL1=:p1上 当匹配时 更新集t.COL3=:p3 当不匹配时 插入列1、列2、列3 值:p1,:p2,:p3


您必须返回一些内容才能进行insert

Yeh这没有帮助,因为update语句只会更新CREATEDATE和USERID,如果我需要更新COLA、COLB或COLC中的任何一个呢?如下所示:更新TABLEA SET COLA='1'其中COLA='2'。我花了一段时间,但我想我在开车回家的时候发现了一个黑客。在查看代码时,我并不清楚。更新主键几乎总是一个坏主意。主键的整体思想是,它应该定义记录特有的内容,并且不应该更改。不幸的是,您留下了一个需要执行此操作的模式!我同意。DBA承包商宣布它更容易维护。我提出了分离索引信息的观点
从实际数据来看,否则会使查询变得非常复杂。在我的例子中,ROWID已经足够了,因为它正在对自身进行查询。如果我使用连接,就会出现问题。我对你的答案投了更高的票,因为这是一种正确的格式,可以在一个有建筑感的设计上进行自我合并。@sksallaj-非常感谢你的解释,这正是我想要的。但我这里有个小问题。当我从ORDERBY子句运行此查询时,得到的“COLA”是无效标识符。这是dual要求的订单吗?因为我们只得到一个记录,我理解我们需要通过ASC订购。请帮帮我,似乎没有人在merge语句中提到这种情况。。