如何使用Merge语句更新目标表

时间:2018-02-26 04:57:22

标签: sql oracle

我尝试使用merge表更新目标表中的列,方法是将目标表与源表连接并获得以下错误。

我需要将TRADE表中的offer_id,order_Date和Doc_receipt_date与offer_trade_by_date,offer_start_date,offer_end_date进行比较。在这里,我试图验证交易是否在该时间段内完成。如果及时完成交易,则通过支票(即' Y')。如果没有及时完成交易,那么它没有通过支票(即' N')。如果我们没有任何信息来检查条件(即当DOCK_RECEIPT_DATE为NULL时),那么(' X')。为了实现这个检查,我在下面写了代码并得到以下错误。

ORA:30926无法在源表中获得稳定的行集。

检查下表中的数据。

贸易/目标表

KEYID      DPBL_OFFER      ORD_DATE    DOC_RECPT_DT     TRADE_DATE_MET

 1          107           30-SEP-17     01-JAN-17              X
 2          107           22-SEP-17      NULL                  X
 3          107           07-OCT-17      NULL                  X
 4          107           24-NOV-17     28-NOV-17              X
 5          106           24-AUG-17     11-SEP-17              X
 6          105           11-JUN-17       NULL                 X
 7          108           05-SEP-17     13-SEP-17              X
 8          109           28-JUL-17     10-AUG-17              X
 9          110           01-SEP-17     14-SEP-17              X

PROD_OFFER /来源表)

Offer_id                Trade_by_Date
 106                      14-OCT-17
 107                      14-NOV-17
 105                      02-AUG-17
 108                      18-NOV-17
 109                      14-OCT-17
 110                      18-NOV-17

OFFER_START_END_V /来源表2)

Offer_id      Offer_Period   Offer_Start_Date    Offer_End_Date
  106             1             27-JUL-17          27-JUL-17
  106             2             28-JUL-17          14-OCT-17
  107             1             15-SEP-17          23-JAN-18
  105             1             01-JUN-17          02-AUG-17
  108             1             23-AUG-17          14-SEP-17
  108             2             16-SEP-17          19-SEP-17
  110             1             23-AUG-17          14-SEP-17
  110             2             16-SEP-17          19-SEP-17 
  109             1             02-JUL-17          12-NOV-17

此目标表中的keyid是PK,DPBL_OFFER id是来自目标表的offer_id,并且不是FK。

检查以下代码

MERGE INTO TRADE TB
   USING (
            SELECT T1.KEYID, T1.DPBL_OFFER
              , CASE WHEN T1.ORD_DATE >= T3.OFFER_START_DATE AND
                          T1.ORD_DATE <= T2.TRADE_BY_DATE AND
                          T1.COD_RECPT_DATE <= T3.OFFER_END_DATE
                     THEN 'Y'
               WHEN T1.ORD_DATE < T3.OFFER_START_DATE AND
                          T1.ORD_DATE > T2.TRADE_BY_DATE AND
                          T1.COD_RECPT_DATE > T3.OFFER_END_DATE
                THEN 'N'
            ELSE 'X'
           END AS TRADE_DATE_MET
         FROM TRADE T1
         JOIN PROD_OFFER  T2
               ON T1.DPBL_OFFER_ID = T2.OFFER_ID
          JOIN OFFER_START_END_V T3
                ON T1.DPBL_OFFER_ID = T3.OFFER_ID) JT

        ON TB.KEYID  = JT.KEYID
          AND TB.DPBL_OFFER_ID = JT.OFFER_ID
WHEN MATCH THEN
         UPDATE SET TB. TRADE_DATE_MET = JT.TRADE_DATE_MET;

有人可以帮助我克服这个错误。?

仅供参考: - 我使用的是Oracle 11g。

1 个答案:

答案 0 :(得分:0)

该错误通常意味着目标表中至少有一行(至少有一行,可能有很多行),源表中至少有两行不同的行(或三表连接的结果,在你的情况下)满足MERGE语句中的ON条件 - 并且UPDATE子句中使用的值实际上是不同的。

在您的情况下:对于KEYID = 5,DPBL_OFFER为106.这将加入PROD_OFFER中的一行和OFFER_START_END_V中的两个不同的行。并且TRADE_END_MET对于三表连接中的两个结果行是不同的。 (或者,如果它是相同的 - 让两个人说'N&#39;对于这个KEYID,那么也许对于KEYID = 7,DPBL_OFFER = 108,它也加入 2最后一个表中的不同行,得到的TRADE_END_MET在两行中都不相同。)

这种错误通常是致命的,因为它实际上是逻辑上的错误,无论代码(甚至语言)如何。也就是说,即使你用普通语言表达问题并且你试图用纸和笔来解决它,你也不能,因为它是自相矛盾的。

它类似于,但更复杂:目标表具有列ID(主键)和FLAG(当前为空)。源具有列ID和标志。 Target有一行(1,null)。来源有两行,(1,&#39; Y&#39;)和(1,&#39; N&#39;)。您希望使用源更新目标中的标志。你明白为什么这没有意义吗?这正是你遇到的那种问题。

单独运行三向连接(&#34;源表&#34;用于MERGE)并检查KEYID = 5和7的TRADE_END_MET值 - 您可能会发现问题。