Sql 中 Merge 的用法

本文介绍SQL Server 2008中Merge命令的应用场景与语法,通过具体案例展示如何高效地同步两个表的数据,包括更新、插入及删除操作,并提供优化建议。

Sql 2008 Merge 的用法

Merge Sql2008 新增命令之一,它可以基于两表连接的某个条件的结果操作数据 (INSERT, UPDATE, and DELETE), 它的好处是少写一些代码,多做一些事情, 以下我们将充分说明这个优点。

有这样一个需求:

USE tempdb;

IF OBJECT_ID('dbo.Customers', 'U') IS NOT NULL DROP TABLE dbo.Customers;

GO

CREATE TABLE dbo.Customers

(

custid INT NOT NULL,

companyname VARCHAR(25) NOT NULL,

phone VARCHAR(20) NOT NULL,

address VARCHAR(50) NOT NULL,

CONSTRAINT PK_Customers PRIMARY KEY(custid)

);

INSERT INTO dbo.Customers(custid, companyname, phone, address)

VALUES

(1, 'cust 1', '(111) 111-1111', 'address 1'),

(2, 'cust 2', '(222) 222-2222', 'address 2'),

(3, 'cust 3', '(333) 333-3333', 'address 3'),

(4, 'cust 4', '(444) 444-4444', 'address 4'),

(5, 'cust 5', '(555) 555-5555', 'address 5');

IF OBJECT_ID('dbo.CustomersStage', 'U') IS NOT NULL DROP TABLE dbo.CustomersStage;

GO

CREATE TABLE dbo.CustomersStage

(

custid INT NOT NULL,

companyname VARCHAR(25) NOT NULL,

phone VARCHAR(20) NOT NULL,

address VARCHAR(50) NOT NULL,

CONSTRAINT PK_CustomersStage PRIMARY KEY(custid)

);

INSERT INTO dbo.CustomersStage(custid, companyname, phone, address)

VALUES

(2, 'AAAAA', '(222) 222-2222', 'address 2'),

(3, 'cust 3', '(333) 333-3333', 'address 3'),

(5, 'BBBBB', 'CCCCC', 'DDDDD'),

(6, 'cust 6 (new)', '(666) 666-6666', 'address 6'),

(7, 'cust 7 (new)', '(777) 777-7777', 'address 7');

要求将dbo.CustomersStage中的数据合并入dbo.Customers,合并规则如下:

a. dbo.Customers dbo.CustomersStage 都有的一模一样的数据在dbo.Customers中保持不变

b. dbo.Customers dbo.CustomersStage custid 相同的则按照dbo.CustomersStage中的companyname, phone, address数据更新对应的dbo.Customers数据

c. 不存在于dbo.Customerscustid)中,但存在于dbo.CustomersStagecustid)的数据要插入dbo.Customers

大家也许可以用多条Sql来解决:

规则a 不需要操作

Sql for 规则b:

Update C

set C.companyname = cs.companyname,

C.phone = cs.phone,

C.address =cs.address

from dbo.Customers as C

inner join dbo.CustomersStage CS

on CS.custid = C.custid

Sql for 规则c:

insert into

dbo.Customers(custid, companyname, phone, address)

select custid, companyname, phone, address

from dbo.CustomersStage where custid not in

(select custid from dbo.Customers)

下面看看使用Merge解决这个问题的语句:

MERGE INTO dbo.Customers AS TGT

USING dbo.CustomersStage AS SRC

ON TGT.custid = SRC.custid

WHEN MATCHED THEN

UPDATE SET

TGT.companyname = SRC.companyname,

TGT.phone = SRC.phone,

TGT.address = SRC.address

WHEN NOT MATCHED THEN

INSERT (custid, companyname, phone, address)

VALUES (SRC.custid, SRC.companyname, SRC.phone, SRC.address);

如果再加一条规则d:删除dbo.Customerscustid 不在dbo.CustomersStage中的记录

如果不用merge 就要再加一句:

delete from dbo.Customers

where custid not in

(select custid from dbo.CustomersStage)

但如果用merge,注意高亮部分是为规则d加的:

MERGE dbo.Customers AS TGT

USING dbo.CustomersStage AS SRC

ON TGT.custid = SRC.custid

WHEN MATCHED THEN

UPDATE SET

TGT.companyname = SRC.companyname,

TGT.phone = SRC.phone,

TGT.address = SRC.address

WHEN NOT MATCHED THEN

INSERT (custid, companyname, phone, address)

VALUES (SRC.custid, SRC.companyname, SRC.phone, SRC.address)

WHEN NOT MATCHED BY SOURCE THEN

DELETE;

但是这里有个问题,当custid在两个表中匹配上时,无论对应的记录是否一致,以上语句都是要更新dbo.Customers的,这样如果相同的很多,不起作用的update就浪费了很多资源,解决的办法(高亮部分)是:

MERGE dbo.Customers AS TGT

USING dbo.CustomersStage AS SRC

ON TGT.custid = SRC.custid

WHEN MATCHED AND

( TGT.companyname <> SRC.companyname

OR TGT.phone <> SRC.phone

OR TGT.address <> SRC.address) THEN

UPDATE SET

TGT.companyname = SRC.companyname,

TGT.phone = SRC.phone,

TGT.address = SRC.address

WHEN NOT MATCHED THEN

INSERT (custid, companyname, phone, address)

VALUES (SRC.custid, SRC.companyname, SRC.phone, SRC.address);

### PL/SQLMERGE INTO 语句的语法及使用示例 在 PL/SQL 中,`MERGE INTO` 是一种强大的 SQL 语句,用于将数据从一个表合并到另一个表中。它可以根据匹配条件执行插入或更新操作,从而避免了分别编写 `INSERT` 和 `UPDATE` 语句的繁琐过程。以下是 `MERGE INTO` 的详细语法和使用示例。 #### 1. 基本语法 `MERGE INTO` 语句的基本语法如下: ```sql MERGE INTO target_table t USING source_table s ON (merge_condition) WHEN MATCHED THEN UPDATE SET t.column1 = s.column1, t.column2 = s.column2, ... WHEN NOT MATCHED THEN INSERT (t.column1, t.column2, ...) VALUES (s.column1, s.column2, ...); ``` - `target_table`: 目标表,即将被更新或插入数据的表。 - `source_table`: 源表,提供数据的表。 - `merge_condition`: 匹配条件,用于确定目标表中的行是否与源表中的行匹配。 - `WHEN MATCHED THEN UPDATE`: 当目标表中的行与源表中的行匹配时执行更新操作。 - `WHEN NOT MATCHED THEN INSERT`: 当目标表中没有与源表匹配的行时执行插入操作。 #### 2. 示例代码 以下是一个具体的 `MERGE INTO` 使用示例: 假设我们有两个表:`employees` 和 `new_employees`。我们需要根据 `employee_id` 将 `new_employees` 表中的数据合并到 `employees` 表中。 ```sql -- 创建 employees 表 CREATE TABLE employees ( employee_id NUMBER, first_name VARCHAR2(50), salary NUMBER ); -- 创建 new_employees 表 CREATE TABLE new_employees ( employee_id NUMBER, first_name VARCHAR2(50), salary NUMBER ); -- 插入测试数据 INSERT INTO employees (employee_id, first_name, salary) VALUES (1, 'John', 5000); INSERT INTO employees (employee_id, first_name, salary) VALUES (2, 'Jane', 6000); INSERT INTO new_employees (employee_id, first_name, salary) VALUES (1, 'John', 7000); INSERT INTO new_employees (employee_id, first_name, salary) VALUES (3, 'Mike', 8000); -- 执行 MERGE INTO 语句 MERGE INTO employees e USING new_employees ne ON (e.employee_id = ne.employee_id) WHEN MATCHED THEN UPDATE SET e.salary = ne.salary WHEN NOT MATCHED THEN INSERT (e.employee_id, e.first_name, e.salary) VALUES (ne.employee_id, ne.first_name, ne.salary); ``` 在此示例中: - 如果 `employees` 表中的 `employee_id` 与 `new_employees` 表中的 `employee_id` 匹配,则更新 `salary` 字段[^4]。 - 如果 `employees` 表中不存在匹配的 `employee_id`,则插入新的记录[^4]。 #### 3. 注意事项 - `MERGE INTO` 语句要求 `ON` 子句中的条件必须能够唯一标识目标表中的行。 - 如果需要对多个列进行更新或插入,可以在 `UPDATE SET` 和 `INSERT` 部分中列出所有相关列。 - 在某些情况下,可能需要结合 `WHERE` 子句进一步限制更新或插入的范围。 #### 4. 应用场景 `MERGE INTO` 语句通常用于以下场景: - 数据同步:将一个表中的数据同步到另一个表中。 - 数据整合:将多个来源的数据整合到一个目标表中。 - 数据更新与插入:同时执行更新和插入操作,减少复杂性[^5]。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值