将 MERGE 语句转换为 UPDATE 语句
Convert MERGE statement to UPDATE statement
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
合并到上面的实现中?
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 设置:
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 | null | B
3 | 345678 | C
4 | 123456 | D
5 | 123456 | E
db<>fiddle here
更新:
如果您查看 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
各一次。
将其与 UPDATE
语句的 EXPLAIN PLAN
进行比较:
| 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 here
您可以将这样的嵌套子查询与 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
);
感谢 fiddle @MTO
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
合并到上面的实现中?
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 设置:
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 | null | B 3 | 345678 | C 4 | 123456 | D 5 | 123456 | E
db<>fiddle here
更新:
如果您查看 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
各一次。
将其与 UPDATE
语句的 EXPLAIN PLAN
进行比较:
| 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 here
您可以将这样的嵌套子查询与 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
);
感谢 fiddle @MTO