简体   繁体   中英

How to update a target table with Merge statement

I'm trying to update a column in target table using merge statement by joining target table with source tables and getting the following error.

I need to compare a offer_id, order_Date and Doc_receipt_date from TRADE table with offer_trade_by_date, offer_start_date, offer_end_date. Here I'm trying to verify the trade is done with in the time period. If TRADE is done in time then it's pass the check (ie 'Y'). If TRADE is not done in time then it didn't pass the check (ie 'N'). If we don't have any information to check the condition (ie when DOCK_RECEIPT_DATE is NULL) then ('X'). To achieve this check I wrote below code and getting the following error.

ORA: 30926 unable to get a stable set of rows in the source table.

Check the data in my tables below.

TRADE / Target table

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 /Source table)

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 /Source Table 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

Here keyid in my target table is PK and DPBL_OFFER id is offer_id from target table and isn't FK.

Check below code

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;

Can some one help me to overcome this error.?

FYI:- I'm using Oracle 11g.

That error generally means that there is at least one row in the target table (at least one, there may be many) for which there are at least TWO different rows in the source table (or result of three-table join, in your case) satisfying the ON condition(s) in the MERGE statement - and for which the values used in the UPDATE clause are actually different.

In your case: for KEYID = 5, DPBL_OFFER is 106. This joins to one row in PROD_OFFER and two different rows in OFFER_START_END_V. And the TRADE_END_MET is different for the two resulting rows in the three-table join. (Or, if it is the same - let's say 'N' for both - for this KEYID, then perhaps for KEYID= 7, with DPBL_OFFER = 108, which also joins to two different rows in the last table, the resulting TRADE_END_MET is not the same in both rows.)

This kind of error is usually fatal, since it is in fact an error in logic, regardless of code (or even of language). That is, even if you express the problem in common language and you try to solve it with paper and pencil, you can't, because it is self contradictory.

It is similar to, but more complicated than: Target table has columns ID (primary key) and FLAG (currently null). Source has columns ID and flag. Target has one row (1, null). Source has two rows, (1, 'Y') and (1, 'N'). You want to use the source to update the flag in the target. Do you see why that doesn't make sense? This is exactly the kind of problem you are having.

Run the three-way join by itself (the "source table" for the MERGE) and inspect the TRADE_END_MET values for KEYID = 5 and 7 - you will likely find the problem.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM