跳到主要内容

MERGE

引入或更新: v1.2.241

根据语句中指定的条件和匹配标准,对目标表中的行执行INSERT、UPDATE或DELETE操作,使用指定源中的数据。

数据源(可以是子查询)通过JOIN表达式与目标数据链接。该表达式评估源中的每一行是否能在目标表中找到匹配,然后确定在下一步执行中应进入哪种类型(MATCHED或NOT MATCHED)的子句。

Alt text

MERGE语句通常包含一个MATCHED和/或NOT MATCHED子句,指示Databend如何处理匹配和不匹配的情况。对于MATCHED子句,您可以选择对目标表执行UPDATE或DELETE操作。相反,对于NOT MATCHED子句,可用的选择是INSERT。

多个MATCHED & NOT MATCHED子句

MERGE语句可以包含多个MATCHED和/或NOT MATCHED子句,使您能够根据MERGE操作中满足的条件指定不同的操作。

Alt text

如果MERGE语句包含多个MATCHED子句,则需要为除最后一个子句外的每个子句指定条件。这些条件决定了相关操作的执行标准。Databend按指定顺序评估条件。一旦满足条件,它将触发指定的操作,跳过任何剩余的MATCHED子句,然后继续处理源中的下一行。如果MERGE语句还包含多个NOT MATCHED子句,Databend以类似的方式处理它们。

语法

MERGE INTO <target_table>
USING (SELECT ... ) [AS] <alias> ON <join_expr> { matchedClause | notMatchedClause } [ ... ]

matchedClause ::=
WHEN MATCHED [ AND <condition> ] THEN
{ UPDATE SET <col_name> = <expr> [ , <col_name2> = <expr2> ... ] | UPDATE * | DELETE }

notMatchedClause ::=
WHEN NOT MATCHED [ AND <condition> ] THEN
{ INSERT ( <col_name> [ , <col_name2> ... ] ) VALUES ( <expr> [ , ... ] ) | INSERT * }
参数描述
UPDATE *使用源中相应行的值更新目标表中匹配行的所有列。这要求源和目标之间的列名一致(尽管它们的顺序可以不同),因为在更新过程中,匹配是基于列名进行的。
INSERT *使用源行的值将新行插入目标表。

输出

MERGE提供数据合并结果的摘要,包含以下列:

描述
number of rows inserted添加到目标表的新行数。
number of rows updated目标表中修改的现有行数。
number of rows deleted从目标表中删除的行数。

示例

示例1: 带有多个MATCHED子句的合并

此示例使用MERGE将员工数据从'employees'同步到'salaries',根据指定标准插入和更新薪资信息。

-- 创建'employees'表作为合并的源
CREATE TABLE employees (
employee_id INT,
employee_name VARCHAR(255),
department VARCHAR(255)
);

-- 创建'salaries'表作为合并的目标
CREATE TABLE salaries (
employee_id INT,
salary DECIMAL(10, 2)
);

-- 插入初始员工数据
INSERT INTO employees VALUES
(1, 'Alice', 'HR'),
(2, 'Bob', 'IT'),
(3, 'Charlie', 'Finance'),
(4, 'David', 'HR');

-- 插入初始薪资数据
INSERT INTO salaries VALUES
(1, 50000.00),
(2, 60000.00);

-- 启用MERGE INTO

-- 根据'employees'中的员工详情将数据合并到'salaries'
MERGE INTO salaries
USING (SELECT * FROM employees) AS employees
ON salaries.employee_id = employees.employee_id
WHEN MATCHED AND employees.department = 'HR' THEN
UPDATE SET
salaries.salary = salaries.salary + 1000.00
WHEN MATCHED THEN
UPDATE SET
salaries.salary = salaries.salary + 500.00
WHEN NOT MATCHED THEN
INSERT (employee_id, salary)
VALUES (employees.employee_id, 55000.00);

┌──────────────────────────────────────────────────┐
│ number of rows inserted │ number of rows updated │
├─────────────────────────┼────────────────────────┤
22
└──────────────────────────────────────────────────┘

-- 合并后从'salaries'表中检索所有记录
SELECT * FROM salaries;

┌────────────────────────────────────────────┐
│ employee_id │ salary │
├─────────────────┼──────────────────────────┤
355000.00
455000.00
151000.00
260500.00
└────────────────────────────────────────────┘

示例2: 带有UPDATE * & INSERT *的合并

此示例使用MERGE在target_table和source_table之间同步数据,使用源中的值更新匹配行并插入不匹配的行。

-- 创建目标表target_table
CREATE TABLE target_table (
ID INT,
Name VARCHAR(50),
Age INT,
City VARCHAR(50)
);

-- 向target_table插入初始数据
INSERT INTO target_table (ID, Name, Age, City)
VALUES
(1, 'Alice', 25, 'Toronto'),
(2, 'Bob', 30, 'Vancouver'),
(3, 'Carol', 28, 'Montreal');

-- 创建源表source_table
CREATE TABLE source_table (
ID INT,
Name VARCHAR(50),
Age INT,
City VARCHAR(50)
);

-- 向source_table插入初始数据
INSERT INTO source_table (ID, Name, Age, City)
VALUES
(1, 'David', 27, 'Calgary'),
(2, 'Emma', 29, 'Ottawa'),
(4, 'Frank', 32, 'Edmonton');

-- 启用MERGE INTO

-- 将source_table中的数据合并到target_table
MERGE INTO target_table AS T
USING (SELECT * FROM source_table) AS S
ON T.ID = S.ID
WHEN MATCHED THEN
UPDATE *
WHEN NOT MATCHED THEN
INSERT *;

┌──────────────────────────────────────────────────┐
│ number of rows inserted │ number of rows updated │
├─────────────────────────┼────────────────────────┤
12
└──────────────────────────────────────────────────┘

-- 合并后从'target_table'中检索所有记录
SELECT * FROM target_table order by ID;

┌─────────────────────────────────────────────────────────────────────────┐
│ id │ name │ age │ city │
├─────────────────┼──────────────────┼─────────────────┼──────────────────┤
1 │ David │ 27 │ Calgary │
2 │ Emma │ 29 │ Ottawa │
3 │ Carol │ 28 │ Montreal │
4 │ Frank │ 32 │ Edmonton │
└─────────────────────────────────────────────────────────────────────────┘