Преобразовать оператор MERGE в оператор UPDATE - PullRequest
1 голос
/ 11 октября 2019
MERGE INTO TABLE1 t1
USING TABLE2 t2
ON (t1.ID = t2.ID) 
WHEN MATCHED THEN UPDATE 
  SET t1.PHONE_NUMBER = CASE 
                          WHEN t1.type in ('A','B') THEN  t2.phone_number 
                          ELSE NVL(t2.phone_number, t1.phone_number)
                        END

Необходимо преобразовать выше MERGE в оператор UPDATE.

Я пробовал следующее:

UPDATE TABLE1 t1 
   SET t1.PHONE_NUMBER = (
                          SELECT t2.PHONE_NUMBER 
                            FROM TABLE2 t2, TABLE1 t3 
                           WHERE t3.type in ('A','B') 
                             AND t3.ID = t2.ID
                         )

Как включить CASE в вышеприведенную реализацию

Ответы [ 2 ]

1 голос
/ 11 октября 2019

Вы можете использовать такой вложенный подзапрос с RIGHT JOIN:

update table1 t 
   set t.phone_number = (
                          select tt.phone_number
                            from( 
                                 select case 
                                        when t1.type in ('A','B') then  t2.phone_number 
                                        else nvl(t2.phone_number, t1.phone_number)
                                        end as phone_number, 
                                        nvl(t2.ID,t1.ID) as ID
                                   from table2 t2
                                  right join table1 t1 
                                     on t1.ID = nvl(t2.ID,t1.ID)
                                 ) tt 
                            where tt.ID = t.ID
                           );

Демо

спасибо заскрипка @ МТО

1 голос
/ 11 октября 2019

Оператор MERGE будет более эффективным, и вы, вероятно, должны его использовать;однако вы можете использовать:

UPDATE table1 t1
SET PHONE_NUMBER = NVL(
                     ( SELECT t2.phone_number
                       FROM   table2 t2
                       WHERE  t1.id = t2.id ),
                     CASE
                     WHEN t1.type IN ( 'A', 'B' )
                     THEN NULL
                     ELSE t1.phone_number
                     END
                   )
WHERE EXISTS ( SELECT 1 FROM table2 t2 WHERE t1.id = t2.id );

Oracle Setup :

CREATE TABLE table1 ( id, phone_number, type ) AS
SELECT 1, 123456, 'A' FROM DUAL UNION ALL
SELECT 2, 123456, 'B' FROM DUAL UNION ALL
SELECT 3, 123456, 'C' FROM DUAL UNION ALL
SELECT 4, 123456, 'D' FROM DUAL UNION ALL
SELECT 5, 123456, 'E' FROM DUAL;

CREATE TABLE table2 ( id, phone_number ) AS
SELECT 1, 234567 FROM DUAL UNION ALL
SELECT 2, NULL   FROM DUAL UNION ALL
SELECT 3, 345678 FROM DUAL UNION ALL
SELECT 4, NULL   FROM DUAL;

Вывод :

После запусказатем обновите:

SELECT * FROM table1

Выводит то же самое, что и оператор MERGE:

ID | PHONE_NUMBER | TYPE
-: | -----------: | :---
 1 |       234567 | A   
 2 |         <em>null</em> | B   
 3 |       345678 | C   
 4 |       123456 | D   
 5 |       123456 | E   

db <> fiddle здесь


Обновление :

Если вы посмотрите на EXPLAIN PLAN для оператора MERGE:

| PLAN_TABLE_OUTPUT                                                               |
| :------------------------------------------------------------------------------ |
| Plan hash value: 3423411568                                                     |
|                                                                                 |
| ------------------------------------------------------------------------------- |
| | Id  | Operation            | Name   | Rows  | Bytes | Cost (%CPU)| Time     | |
| ------------------------------------------------------------------------------- |
| |   0 | MERGE STATEMENT      |        |     4 |   168 |     7  (15)| 00:00:01 | |
| |   1 |  MERGE               | TABLE1 |       |       |            |          | |
| |   2 |   VIEW               |        |       |       |            |          | |
| |*  3 |    HASH JOIN         |        |     4 |   268 |     7  (15)| 00:00:01 | |
| |   4 |     TABLE ACCESS FULL| TABLE2 |     4 |   104 |     3   (0)| 00:00:01 | |
| |   5 |     TABLE ACCESS FULL| TABLE1 |     5 |   205 |     3   (0)| 00:00:01 | |
| ------------------------------------------------------------------------------- > 

Тогда он читает только TABLE1 и TABLE2 по одному разу.

Сравните это с EXPLAIN PLAN для оператора UPDATE:

| PLAN_TABLE_OUTPUT                                                              |
| :----------------------------------------------------------------------------- |
| Plan hash value: 735598124                                                     |
|                                                                                |
| ------------------------------------------------------------------------------ |
| | Id  | Operation           | Name   | Rows  | Bytes | Cost (%CPU)| Time     | |
| ------------------------------------------------------------------------------ |
| |   0 | UPDATE STATEMENT    |        |     4 |   168 |    23  (22)| 00:00:01 | |
| |   1 |  UPDATE             | TABLE1 |       |       |            |          | |
| |*  2 |   HASH JOIN SEMI    |        |     4 |   168 |     7  (15)| 00:00:01 | |
| |   3 |    TABLE ACCESS FULL| TABLE1 |     5 |   145 |     3   (0)| 00:00:01 | |
| |   4 |    TABLE ACCESS FULL| TABLE2 |     4 |    52 |     3   (0)| 00:00:01 | |
| |*  5 |   TABLE ACCESS FULL | TABLE2 |     1 |    26 |     3   (0)| 00:00:01 | |
| ------------------------------------------------------------------------------ |

Затем он будет читать из TABLE1 один раз и TABLE2 дважды;так что MERGE, вероятно, будет более производительным запросом .... но вы можете сделать это с UPDATE, если хотите.

db <> fiddle здесь

...