迁移 Oracle 的 Merge into 语句,从未如此轻松!

数据库 Oracle
在 Oracle 中我们可以使用 MERGE INTO 语句,有条件地插入、更新和删除一个表中的行。那么这种语句迁移到 PostgreSQL,会不会有困难?

PostgreSQL MERGE 语句简介

PostgreSQL 15 引入了MERGE语句,可将INSERT、UPDATE和DELETE操作合并到一个语句中,来简化数据操作。MERGE语句通常被称为UPSERT语句。

如果使用的是早期版本的 PostgreSQL,则应考虑使用INSERT... ON CONFLICT语句。

下面是MERGE语句的语法:

MERGE INTO target_table
USING source_query
ON merge_condition
WHEN MATCH [AND condition] THEN {merge_update | merge_delete | DO NOTHING }
WHEN NOT MATCHED [AND condition] THEN { merge_insert | DO NOTHING };

在此语法中:

• target_table是要修改数据的表(INSERT、UPDATE和DELETE)。

• source_query是一个源表或 SELECT 语句,为合并操作提供数据。

• ON merge_condition:此子句指定匹配源表和目标表之间的行的条件。

• WHEN MATCHED THEN:此子句定义了匹配合并条件的行上的操作语句。该条件为执行 update 或 delete 语句提供了附加条件。如果您不想对匹配行执行任何操作,可以使用DO NOTHING选项。

• WHEN NOT MATCHED THEN:此子句定义了不匹配合并条件的行上的操作语句。您可以指定 insert 语句向目标表添加新行,也可以使用DO NOTHING忽略不匹配的行。

请注意,merge_insert、merg_update和merge_delete语句,与常规的INSERT、UPDATE和DELETE语句略有不同。

merge_insert是不带表名的INSERT语句:

INSERT (column1, ...)
VALUES(value1,...);

merge_update语句是不带表名和WHERE子句的UPDATE语句:

UPDATE SET
   column1 = value1, 
   column2 =value2,
   ...;

merge_delete语句就是简单的DELETE关键字:

DELETE

成功完成后,MERGE语句会返回下面的命令标记:

MERGE total_count

在此标记中,total_acount是插入、更新或删除的行的总数。如果total_count为零,则意味着没有行被更改。

MERGE语句对于在表之间同步数据很有用,允许您有效地让目标表与源表中的更改保持同步。

PostgreSQL MERGE 语句示例

让我们来探索一些使用MERGE语句的示例。

0) 设置样例表

首先,创建两个表,名为leads和customers:

CREATE TABLE leads(
    lead_id serial PRIMARY key,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL UNIQUE,
    active bool NOT NULL DEFAULT TRUE
);
CREATE TABLE customers(
    customer_id serial PRIMARY key,
    name VARCHAR(255) NOT NULL,
    email VARCHAR(255) NOT NULL UNIQUE,
    active bool NOT NULL DEFAULT TRUE
);

我们将使用MERGE语句来合并两个表的数据。

1) 使用 PostgreSQL MERGE 语句将源表的行插入目标表

首先,插入两行到leads表中:

INSERT INTO leads(name, email)
VALUES
   ('John Doe', 'john.doe@gmail.com'),
   ('Jane Doe', 'jane.doe@yahoo.com')
RETURNING *;

输出:

lead_id |   name   |       email        | active
---------+----------+--------------------+--------
       1 | John Doe | john.doe@gmail.com | t
       2 | Jane Doe | jane.doe@yahoo.com | t
(2 rows)

第二步,使用MERGE语句将leads表中的行插入到customers表中:

MERGE INTO customers c
USING leads l ON c.email = l.email
WHEN NOT MATCHED THEN 
   INSERT (name, email)
   VALUES(l.name, l.email);

在此语句中,我们使用了leads和customers表的email列作为合并条件。

如果leads表中的email与customers表中的email不匹配,则MERGE语句会将新行插入到customers表中。

输出:

MERGE 2

输出表明已成功插入两行。

第三步,从customers表中检索数据:

SELECT * FROM customers;

输出:

customer_id |   name   |       email        | active
-------------+----------+--------------------+--------
           1 | John Doe | john.doe@gmail.com | t
           2 | Jane Doe | jane.doe@yahoo.com | t
(2 rows)

2) 使用 MERGE 语句将源表的行更改和插入目标表

首先,插入一个新行到leads表中,并更新 id 为 2 的行的name:

INSERT INTO leads(name, email)
VALUES('Alice Smith', 'alice.smith@outlook.com');

UPDATE leads
SET name = 'Jane Gate'
WHERE lead_id = 2;

第二步,从leads表中检索数据:

SELECT * FROM leads
ORDER BY id;

输出:

lead_id |    name     |          email          | active
---------+-------------+-------------------------+--------
       1 | John Doe    | john.doe@gmail.com      | t
       2 | Jane Gate   | jane.doe@yahoo.com      | t
       3 | Alice Smith | alice.smith@outlook.com | t
(3 rows)

leads表中现在有一个 id 为 2 的修改过的行,和一个 id 为 3 的新行。

第三步,将leads表中的新行添加到customers表中,并对更新的行更改name和email:

MERGE INTO customers c
USING leads l ON c.email = l.email
WHEN NOT MATCHED THEN 
   INSERT (name, email)
   VALUES(l.name, l.email)
WHEN MATCHED THEN
   UPDATE SET 
      name = l.name, 
      email = l.email;

该MERGE语句会匹配email列,将新行插入到customers表中,并根据leads表中的数据更新customers表中的现有行。

输出:

MERGE 3

输出表示已修改三行:

  • • 插入了一个新行。
  • • 更新了两个匹配的行。

3) 使用 MERGE 语句更改、插入和删除行

首先,在leads表中插入一个新行:

INSERT INTO leads(name, email)
VALUES('Bob Climo', 'blob.climo@gmail.com');

第二步,将leads表中 id 为 2 的行的active列设置为false:

UPDATE leads
SET active = false
WHERE lead_id = 2;

第三步,将leads表中 id 为 1 的行的email列设置为 “john.doe@hotmail.com”:

UPDATE leads
SET email = 'john.doe@hotmail.com'
WHERE lead_id = 1;

第四步,从leads表中检索数据:

SELECT * FROM leads
ORDER BY lead_id;

输出:

lead_id |    name     |          email          | active
---------+-------------+-------------------------+--------
       1 | John Doe    | john.doe@hotmail.com    | t
       2 | Jane Gate   | jane.doe@yahoo.com      | f
       3 | Alice Smith | alice.smith@outlook.com | t
       4 | Bob Climo   | blob.climo@gmail.com    | t
(4 rows)

第五步,将leads表中的新行插入到customers表中,从customers表中删除active为false的行,并对active为true的行更新name和email:

MERGE INTO customers c
USING leads l ON c.email = l.email
WHEN NOT MATCHED THEN 
   INSERT (name, email)
   VALUES(l.name, l.email)
WHEN MATCHED AND l.active = false THEN
   DELETE
WHEN MATCHED AND l.active = true THEN
   UPDATE SET 
      name = l.name, 
      email = l.email;

输出:

MERGE 4

最后,从customers表中检索行:

SELECT * FROM customers;

输出:

customer_id |    name     |          email          | active
-------------+-------------+-------------------------+--------
           1 | John Doe    | john.doe@gmail.com      | t
           3 | Alice Smith | alice.smith@outlook.com | t
           4 | Bob Climo   | blob.climo@gmail.com    | t
           5 | John Doe    | john.doe@hotmail.com    | t
(4 rows)

总结

使用MERGE语句有条件地插入、更新和删除一个表中的行。

责任编辑:武晓燕 来源: 红石PG
相关推荐

2019-05-23 10:55:22

Istio灰度发布ServiceMesh

2017-04-21 14:57:57

AndroidSuperTextViTextView

2022-08-12 12:19:13

Cluster检索集群

2013-06-14 10:36:00

2011-04-15 09:26:20

Oraclemerge语句

2020-09-07 13:17:27

编码扩展代码

2019-11-28 19:06:00

华为畅享10S

2020-06-17 10:42:54

shellshell脚本Linux

2009-08-26 20:12:41

BMCBSMITIL

2013-11-28 13:47:37

Android4.4ART模式

2013-10-25 13:35:02

云计算

2024-02-27 18:06:35

2021-11-09 13:59:47

物联网安全设备

2010-04-12 09:36:29

Oacle merge

2021-10-18 13:31:28

Web应用交互式

2010-11-04 11:17:42

DB2 Merge语句

2020-03-03 15:40:51

开发技能代码

2021-02-06 17:49:49

人工智能智能医疗智慧安防

2020-03-17 07:41:50

ApacheKafka系统

2022-06-13 06:33:04

浏览器浏览器插件
点赞
收藏

51CTO技术栈公众号