【问题标题】:How to update a target table with Merge statement如何使用 Merge 语句更新目标表
【发布时间】:2018-08-05 12:09:31
【问题描述】:

我正在尝试使用合并语句更新目标表中的列,方法是将目标表与源表连接起来并得到以下错误。

我需要将 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。

【问题讨论】:

  • 如果你使用的是Oracle 11g,那你为什么要留下MySQL标签呢? (可能是因为你不习惯看标签……请学会这样做。)

标签: sql oracle


【解决方案1】:

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

在您的情况下:对于 KEYID = 5,DPBL_OFFER 为 106。这将连接到 PROD_OFFER 中的一行和 OFFER_START_END_V 中的两个不同行。并且 TRADE_END_MET 对于三表连接中的两个结果行是不同的。 (或者,如果它是相同的 - 假设两者都为 'N' - 对于这个 KEYID,那么可能对于 KEYID= 7,DPBL_OFFER = 108,它也连接到最后一个 两个不同的行表,结果 TRADE_END_MET 在两行中都不相同。)

这种错误通常是致命的,因为它实际上是逻辑错误,与代码(甚至语言)无关。也就是说,即使你用通俗的语言表达这个问题,你试图用纸和铅笔来解决它,你也做不到,因为它是自相矛盾的。

它类似于,但比:目标表具有列 ID(主键)和 FLAG(当前为空)。源具有列 ID 和标志。目标有一行(1,空)。源有两行,(1, 'Y') 和 (1, 'N')。您想使用源来更新目标中的标志。你明白为什么这没有意义吗?这正是您遇到的问题。

自行运行三向连接(MERGE 的“源表”)并检查 KEYID = 5 和 7 的 TRADE_END_MET 值 - 您可能会发现问题。

【讨论】:

    猜你喜欢
    • 2021-01-06
    • 2018-03-11
    • 1970-01-01
    • 2023-03-31
    • 2015-07-14
    • 2013-02-11
    • 1970-01-01
    • 2013-01-26
    • 1970-01-01
    相关资源
    最近更新 更多