简体   繁体   中英

How to Update the Following Table with MERGE in Oracle?

I have the following data set (Oracle 12):

Table X
+---------+--------+---------------+--------+
| COLN    | COLM   | COLK          | COLP   |
+---------+--------+---------------+--------+
| 1       | 500    | K1            | 777    |
+---------+--------+---------------+--------+

Table A
+---------+--------+---------------+--------+
| COL1    | COL2   | COL3          | COL4   |
+---------+--------+---------------+--------+
| 1       | K1     | 500           | B      |
| 1       | K2     | 500           | NULL   |
+---------+--------+---------------+--------+

Table B
+---------+--------+---------+
| COLZ    | COLX   | COLW    |
+---------+--------+---------+
| 1       | K1     | 777     |
| 1       | K2     | 678     |
+---------+--------+---------+

The three tables have the following commonality:

X.COLN = A.COL1 = B.COLZ X.COLk = A.COL2 = B.COLX X.COLM = A.COL3

I need to write a query which retrieves values for the following columns in one query:

X.COLK , X.COLP , B.COLX , B.COLW

The ultimate goal is, if the following conditions are met:

  • If there more than one record in Table A where A.COL1 's and A.COL3 's are matching (and there is a corresponding record in Table X)
  • And one of the rows is not null, eg A.COL4 = B , and another one is NULL

I update Table X to replace X.COLK , X.COLP (K1 and 777) in my MERGE statement with values in Table B ( B.COLX , B.COLW -- K2 and 678).

Is this possible?

MERGE INTO X FX
USING (
    SELECT COLX ONGOING_X, COLW ONGOING_W 
    FROM B 
    WHERE (COLZ, COLX) IN 
        (SELECT COL1, COL2 
         FROM A 
         WHERE COL3 = ? 
            AND COL1 = ? 
            AND COL4 IS NULL)
) NEW_B
    ON (FX.COLk = ?
        AND FX.COLP = ?)
WHEN MATCHED THEN
    UPDATE SET
        FX.COLk = NEW_B.ONGOING_X,
        FX.FOLP = NEW_B.ONGOING_W;

You may do a MERGE using ROWID .

MERGE INTO x tgt USING (
     WITH c AS (
          SELECT col1,
                 col3,
                 MAX(
                      CASE
                           WHEN col4 IS NULL THEN col2
                      END
                 ) AS col2 --Ongoing col2 as indicated from col4
          FROM a
          GROUP BY col1,
                   col3
          HAVING COUNT(
               CASE
                    WHEN col4 IS NULL THEN 1
               END
          ) = 1 AND COUNT(col4) = 1 --Contains one and exactly one NULL and one NON NULL
     ) SELECT x.rowid AS rid,
              b.*
       FROM x
       JOIN c ON c.col1 = x.coln AND c.col3 = x.colm 
       JOIN b ON b.colz = c.col1 AND b.colx = c.col2 --Join with ongoing value from c( a.k.a table A )
)
src ON ( tgt.rowid = src.rid ) --ROWID match
WHEN MATCHED THEN UPDATE SET tgt.colk = src.colx,
tgt.colp = src.colw;

Demo

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