七月 26, 2023
MERGE
语句提供了一种指定单个 SQL 语句的方法,这些语句有条件地对目标表执行INSERT
、UPDATE
或DELETE
操作,否则该任务需要多个逻辑语句。
Oracle 用法
MERGE
语句从源表中选择记录,然后通过指定逻辑结构自动对目标表执行多个 DML 操作。它的主要优点是有助于避免使用多个插入、更新或删除。需要重点注意的是,MERGE
是一个确定性语句。也就是说,一旦行由 MERGE 语句处理,就不能使用相同的MERGE
语句再次处理它。MERGE
有时也称为UPSERT
。
例子
使用MERGE
插入或更新有权获得奖金的员工(按年)。
CREATE TABLE EMP_BONUS(
EMPLOYEE_ID NUMERIC,
BONUS_YEAR VARCHAR2(4),
SALARY NUMERIC,
BONUS NUMERIC,
PRIMARY KEY (EMPLOYEE_ID, BONUS_YEAR)
);
MERGE INTO EMP_BONUS E1
USING (
SELECT EMPLOYEE_ID, FIRST_NAME, SALARY, DEPARTMENT_ID
FROM EMPLOYEES) E2
ON (E1.EMPLOYEE_ID = E2.EMPLOYEE_ID)
WHEN MATCHED THEN
UPDATE SET E1.BONUS = E2.SALARY * 0.5
DELETE WHERE (E1.SALARY >= 10000)
WHEN NOT MATCHED THEN
INSERT (E1.EMPLOYEE_ID, E1.BONUS_YEAR, E1.SALARY, E1.BONUS)
VALUES (E2.EMPLOYEE_ID,
EXTRACT(YEAR FROM SYSDATE),
E2.SALARY,
E2.SALARY * 0.5)
WHERE (E2.SALARY < 10000);
SELECT * FROM EMP_BONUS;
EMPLOYEE_ID BONUS_YEAR SALARY BONUS
103 2017 9000 4500
104 2017 6000 3000
105 2017 4800 2400
106 2017 4800 2400
107 2017 4200 2100
109 2017 9000 4500
110 2017 8200 4100
111 2017 7700 3850
112 2017 7800 3900
113 2017 6900 3450
115 2017 3100 1550
有关详细信息,请参阅 Oracle 文档中的 MERGE。
PostgreSQL 用法
PostgreSQL 不支持使用 SQL 命令MERGE
。作为替代方法,请考虑使用INSERT… ON CONFLICT
语句,该语句可以处理插入子句可能导致冲突的情况,然后将操作重定向为更新。
例子
使用ON CONFLICT
子句处理类似的场景,如 Oracle MERGE
命令所示。
CREATE TABLE EMP_BONUS (
EMPLOYEE_ID NUMERIC,
BONUS_YEAR VARCHAR(4),
SALARY NUMERIC,
BONUS NUMERIC,
PRIMARY KEY (EMPLOYEE_ID, BONUS_YEAR)
);
INSERT INTO EMP_BONUS
(EMPLOYEE_ID, BONUS_YEAR, SALARY)
SELECT EMPLOYEE_ID,
EXTRACT(YEAR FROM NOW()),
SALARY
FROM EMPLOYEES
WHERE SALARY < 10000
ON CONFLICT (EMPLOYEE_ID, BONUS_YEAR)
DO UPDATE SET
BONUS = EMP_BONUS.SALARY * 0.5;
SELECT * FROM EMP_BONUS;
employee_id bonus_year salary bonus
103 2017 9000.00 4500.000
104 2017 6000.00 3000.000
105 2017 4800.00 2400.000
106 2017 4800.00 2400.000
107 2017 4200.00 2100.000
109 2017 9000.00 4500.000
110 2017 8200.00 4100.000
111 2017 7700.00 3850.000
112 2017 7800.00 3900.000
113 2017 6900.00 3450.000
115 2017 3100.00 1550.000
116 2017 2900.00 1450.000
117 2017 2800.00 1400.000
118 2017 2600.00 1300.000
使用ON CONFLICT
子句多次运行同一操作不会生成错误,因为现有记录将重定向到 update 子句。