在 Postgres 的相同 CLAUSE 选项中合并具有两个条件的语句
Merge statement with two conditions in same CLAUSE alternative in Postgres
我在使用 WITH 子句将 Oracle Merge 迁移到 Postgres 时遇到问题。
以下是来自 ORACLE 的示例代码:
SELECT * FROM source;
ID STATUS DESCRIPTION
---------- ---------- -----------------------
1 20 Description of level 1
2 10 Description of level 2
3 20 Description of level 3
4 10 Description of level 4
5 20 Description of level 5
目的地 table 如下:
SELECT * FROM destination;
1 20 Description of level 1
2 10 Description of level 2
3 20 Description of level 3
4 10 Description of level 4
5 20 Description of level 5
6 10 Description of level 6
7 20 Description of level 7
8 10 Description of level 8
9 20 Description of level 9
10 10 Description of level 10
我在 ORACLE 中有 Merge 实现,如下所示:合并时:
MERGE INTO destination d
USING source s
ON (s.id = d.id)
WHEN MATCHED THEN
UPDATE SET d.description = 'Updated'
DELETE WHERE d.status = 10;
5 rows merged.
SELECT * FROM destination;
ID STATUS DESCRIPTION
---------- ---------- -----------------------
1 20 Updated
3 20 Updated
5 20 Updated
6 10 Description of level 6
7 20 Description of level 7
8 10 Description of level 8
9 20 Description of level 9
10 10 Description of level 10
8 rows selected.
我能够使用 CTE 转换在 MATCHED 和 UNMATCHED 子句中都具有一个条件的 Merge。
但不确定如何做(删除和更新),如果我在同一个子句中有两个条件。
已编辑:
我了解 a_horse_with_no_name 分享的答案。但是我对在下面的情况下是否需要做一个嵌套的 CTE 感到困惑。
MERGE INTO destination d
USING source s
ON (s.id = d.id)
WHEN MATCHED THEN
UPDATE SET d.description = 'Updated'
DELETE WHERE d.status = 10
WHEN NOT MATCHED THEN
INSERT (ID, STATUS, DESCRIPTION) VALUES (s.id,s.status,s.description);
如果我的合并语句也不匹配,那我该怎么做。
我不确定这是否是最有效的方法,但它可以满足您的要求:
with updated as (
update destination d
set description = 'Updated'
from source s
where s.id = d.id
and d.status <> 10
returning d.id
)
delete from destination
where id not in (select id from updated)
and exists (select *
from source s
where s.id = destination.id);
它首先更新 destination
中存在于 source
中且状态不是 10 的行。然后删除那些未更新且存在于 source
中的行 table.
我在使用 WITH 子句将 Oracle Merge 迁移到 Postgres 时遇到问题。
以下是来自 ORACLE 的示例代码:
SELECT * FROM source;
ID STATUS DESCRIPTION
---------- ---------- -----------------------
1 20 Description of level 1
2 10 Description of level 2
3 20 Description of level 3
4 10 Description of level 4
5 20 Description of level 5
目的地 table 如下:
SELECT * FROM destination;
1 20 Description of level 1
2 10 Description of level 2
3 20 Description of level 3
4 10 Description of level 4
5 20 Description of level 5
6 10 Description of level 6
7 20 Description of level 7
8 10 Description of level 8
9 20 Description of level 9
10 10 Description of level 10
我在 ORACLE 中有 Merge 实现,如下所示:合并时:
MERGE INTO destination d
USING source s
ON (s.id = d.id)
WHEN MATCHED THEN
UPDATE SET d.description = 'Updated'
DELETE WHERE d.status = 10;
5 rows merged.
SELECT * FROM destination;
ID STATUS DESCRIPTION
---------- ---------- -----------------------
1 20 Updated
3 20 Updated
5 20 Updated
6 10 Description of level 6
7 20 Description of level 7
8 10 Description of level 8
9 20 Description of level 9
10 10 Description of level 10
8 rows selected.
我能够使用 CTE 转换在 MATCHED 和 UNMATCHED 子句中都具有一个条件的 Merge。 但不确定如何做(删除和更新),如果我在同一个子句中有两个条件。
已编辑: 我了解 a_horse_with_no_name 分享的答案。但是我对在下面的情况下是否需要做一个嵌套的 CTE 感到困惑。
MERGE INTO destination d
USING source s
ON (s.id = d.id)
WHEN MATCHED THEN
UPDATE SET d.description = 'Updated'
DELETE WHERE d.status = 10
WHEN NOT MATCHED THEN
INSERT (ID, STATUS, DESCRIPTION) VALUES (s.id,s.status,s.description);
如果我的合并语句也不匹配,那我该怎么做。
我不确定这是否是最有效的方法,但它可以满足您的要求:
with updated as (
update destination d
set description = 'Updated'
from source s
where s.id = d.id
and d.status <> 10
returning d.id
)
delete from destination
where id not in (select id from updated)
and exists (select *
from source s
where s.id = destination.id);
它首先更新 destination
中存在于 source
中且状态不是 10 的行。然后删除那些未更新且存在于 source
中的行 table.