在Postgres中使用相同CLAUSE替代中的两个条件合并语句

时间:2018-02-07 09:44:27

标签: sql postgresql common-table-expression postgresql-9.4

使用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

目的地表如下:

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.

我能够转换一个在MATCHED和MAT中都有一个条件的Merge。使用CTE的UNMATCHED条款。 但是如果我在同一条款中有两个条件,则不确定如何做(DELETE和UPDATE)。

编辑:   我理解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);

如果我的合并声明也没有匹配,那我该怎么办呢。

1 个答案:

答案 0 :(得分:0)

我不确定这是否是最有效的方法,但它可以满足您的需求:

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表中的行。

在线示例:http://rextester.com/KTTOX89581