多应用+插件架构,代码干净,二开方便,首家独创一键云编译技术,文档视频完善,免费商用码云13.8K 广告
>[danger] ## 3.5.1 [插入记录] - 向表中插入一行 要在表中添加一行或多行,请使用`INSERT`语句。 以下是`INSERT`语句的最基本形式: ~~~sql INSERT INTO table_name (column_list) VALUES (value_list); ~~~ 下面更详细地解释这种语法。 首先,`table_name`指定要插入的表的名称。 通常,通过模式名称引用表名称,例如`production.products`,其中`production`是模式名称,`products`是表名称。 其次,`column_list`指定要在其中插入数据的一个或多个列的列表。必须将列列表括在括号中并用逗号分隔列。 如果列在列列表中没有出现,则SQL Server必须能够提供插入值,否则无法插入行。 SQL Server自动对表中可用的列使用以下值,但不会出现在`INSERT`语句的列列表中: * 如果列具有[IDENTITY](http://www.yiibai.com/sqlserver/sql-server-identity.html "IDENTITY")属性,则为下一个增量值。 * 如果列具有指定的默认值,则为默认值。 * 如果列的数据类型是时间戳数据类型,则为当前时间戳值。 * 如果列可以为`NULL`值,则使用`NULL`。 * 如果列是计算列,则使用计算的值。 第三,要在`VALUES`子句中提供插入的值列表。 列列表中的每列必须在值列表中具有相应的值。 此外,必须将值列表括在括号中。 ## SQL Server INSERT语句示例 为了方便演示,创建一个名为`promotions`的新表: ~~~sql CREATE TABLE sales.promotions ( promotion_id INT PRIMARY KEY IDENTITY (1, 1), promotion_name VARCHAR (255) NOT NULL, discount NUMERIC (3, 2) DEFAULT 0, start_date DATE NOT NULL, expired_date DATE NOT NULL ); ~~~ 在本声明中,在`sales`模式中创建了一个名为`promotions`的新表。 `promotions`表有五列,包括:促销标识号(`promotion_id`),名称(`name`),折扣(`discount`),开始日期(`start_date`)和过期日期(`expired_date`)。 `promotion_id`是标识列,因此当向表中添加新行时,SQL Server会自动填充其值。 #### 1\. 基本INSERT示例 以下语句将新行插入`promotions`表: ~~~sql INSERT INTO sales.promotions ( promotion_name, discount, start_date, expired_date ) VALUES ( '2020夏季促销', 0.25, '20200601', '20200901' ); ~~~ 在此示例中,为`promotions`表中的四列指定了值。但没有为`promotion_id`列指定值,因为SQL Server会自动为此列提供值。 如果`INSERT`语句成功执行,将返回插入的行数。 在这种情况下,SQL Server发出以下消息: ~~~shell (1 row affected) ~~~ 要验证插入操作结果,请使用以下查询表中的数据: ~~~sql SELECT * FROM sales.promotions; ~~~ 执行上面查询语句,得到以下结果: ![](https://www.yiibai.com/uploads/article/2019/02/13/194630_72154.png) #### 2\. 插入并返回插入的值 要捕获插入的值,请使用`OUTPUT`子句。 例如,以下语句将新行插入`promotions`表并返回`promote_id`列的插入值: ~~~sql INSERT INTO sales.promotions ( promotion_name, discount, start_date, expired_date ) OUTPUT inserted.promotion_id VALUES ( '2020秋季促销', 0.15, '20201001', '20201101' ); ~~~ 要从多个列中捕获插入的值,请在输出中指定列,如以下语句所示: ~~~sql INSERT INTO sales.promotions ( promotion_name, discount, start_date, expired_date ) OUTPUT inserted.promotion_id, inserted.promotion_name, inserted.discount, inserted.start_date, inserted.expired_date VALUES ( '2020冬季促销', 0.2, '20201201', '20200101' ); ~~~ 执行上面查询语句,得到以下输出结果: ![](https://www.yiibai.com/uploads/article/2019/02/13/223604_24412.png) #### 3\. 将显式值插入标识列 通常,不为标识列指定值,因为SQL Server将自动提供值。但是,在某些情况下,可能希望在标识列中插入值,例如数据迁移。 请参阅以下`INSERT`语句: ~~~sql INSERT INTO sales.promotions ( promotion_id, promotion_name, discount, start_date, expired_date ) OUTPUT inserted.promotion_id VALUES ( 2, '2020春季促销', 0.25, '20200201', '20200301' ); ~~~ SQL Server发出以下错误: ![](https://www.yiibai.com/uploads/article/2019/02/13/223812_61082.png) 要为标识列插入显式值,必须首先执行以下语句: ~~~sql SET IDENTITY_INSERT table_name ON; ~~~ 要关闭标识插入,请使用类似的语句: ~~~sql SET IDENTITY_INSERT table_name OFF; ~~~ 执行以下语句,在`promotion`表中插入标识列的值: ~~~sql SET IDENTITY_INSERT sales.promotions ON; INSERT INTO sales.promotions ( promotion_id, promotion_name, discount, start_date, expired_date ) OUTPUT inserted.promotion_id VALUES ( 2, '2020春季促销', 0.25, '20200201', '20200301' ); SET IDENTITY_INSERT sales.promotions OFF; ~~~ 在此示例中,首先,打开标识插入,然后插入一个具有标识列的显式值的行,最后关闭标识插入。 以下查询显示插入后`promotions`表中的数据: ~~~sql SELECT * FROM sales.promotions; ~~~ >[danger] ## 3.5.2[插入多行] - 使用单个`INSERT`语句将多行插入表中。 要一次向表中添加多行,请使用以下形式的`INSERT`语句: ~~~sql INSERT INTO table_name (column_list) VALUES (value_list_1), (value_list_2), ... (value_list_n); ~~~ 在此语法中,不使用单个值列表,而是使用多个以逗号分隔的值列表进行插入。 使用此形式的`INSERT`语句,一次可以插入的行数为`1000`行。 如果要插入更多行,则应考虑使用多个`INSERT`语句,`BULK INSERT`或派生表。 请注意,此`INSERT`多行语法仅在SQL Server 2008或更高版本中受支持。 ## SQL Server Insert多行示例 我们将使用[上一个教程](http://www.yiibai.com/sqlserver/sql-server-insert.html "上一个教程")中创建的`promotions`表进行演示。如果尚未创建`promotions`表,则可以使用以下`CREATE TABLE`语句: ~~~sql CREATE TABLE sales.promotions ( promotion_id INT PRIMARY KEY IDENTITY (1, 1), promotion_name VARCHAR (255) NOT NULL, discount NUMERIC (3, 2) DEFAULT 0, start_date DATE NOT NULL, expired_date DATE NOT NULL ); ~~~ 以下语句将多个行添加到`promotions`表: ~~~sql -- 先删除表中的所有记录 DELETE FROM sales.promotions; -- 开始插入 INSERT INTO sales.promotions ( promotion_name, discount, start_date, expired_date ) VALUES ( '2020夏季促销', 0.15, '20200601', '20200901' ), ( '2020秋季促销', 0.20, '20201001', '20201101' ), ( '2020冬季促销', 0.25, '20201201', '20210101' ); ~~~ 执行上面插入语句,SQL Server发出以下消息,指示已成功插入三行 - ~~~sql (3 rows affected) ~~~ 通过执行以下查询来验证插入数据: ![](https://www.yiibai.com/uploads/article/2019/02/14/115639_75282.png) >[danger] ## 3.5.3 [INSERT INTO SELECT] - 根据查询结果将数据插入表中。 要将其他表中的数据插入另一个表中,请使用以下SQL Server `INSERT INTO SELECT`语句: ~~~sql INSERT [ TOP ( expression ) [ PERCENT ] ] INTO target_table (column_list) select_query ~~~ 在此语法中,查询语句返回的行将插入`target_table`。 该查询是从任何其他表中检索数据的有效`SELECT`语句。 它必须返回与`column_list`中指定的列对应的值。 `TOP`子句部分是可选的。 它用于指定要插入目标表(`target_table`)的查询返回的行数。 如果使用`PERCENT`选项,则语句将插入行的百分比。 请注意,最好始终将`TOP`子句与`ORDER BY`子句一起使用。 ## INSERT INTO SELECT示例 为了方便演示,下面创建一张`addresses`表: ~~~sql CREATE TABLE sales.addresses ( address_id INT IDENTITY PRIMARY KEY, street VARCHAR (255) NOT NULL, city VARCHAR (50), state VARCHAR (25), zip_code VARCHAR (5) ); ~~~ #### 1\. 将表的所有行插入另一张表示例 以下语句将`customers`表中的所有地址都插入到`addresses`表中: ~~~sql INSERT INTO sales.addresses (street, city, state, zip_code) SELECT street, city, state, zip_code FROM sales.customers ORDER BY first_name, last_name; ~~~ 要验证插入结果,请使用以下查询: ~~~sql SELECT * FROM sales.addresses; ~~~ 执行上面查询语句,得到以下结果: ![](https://www.yiibai.com/uploads/article/2019/02/14/121034_27750.png) #### 2\. 插入一些行的示例 有时,只需要将一张表中的一些行插入到另一张表中。 在这种情况下,可以通过使用[WHERE](http://www.yiibai.com/sqlserver/sql-server-where.html "WHERE")子句中的条件来限制从查询返回的行数。 以下语句将位于城市:`Santa Cruz`和`Baldwin`的商店的地址添加到`address`表中: ~~~sql INSERT INTO sales.addresses (street, city, state, zip_code) SELECT street, city, state, zip_code FROM sales.stores WHERE city IN ('Santa Cruz', 'Baldwin') ~~~ SQL Server返回以下消息,指示已成功插入两行。 ~~~shell (2 rows affected) ~~~ #### 3\. 插入前N行记录 首先,使用以下语句删除`addresses`表中的所有行: ~~~sql TRUNCATE TABLE sales.addresses; ~~~ 其次,要插入按名字和姓氏排序的前`10`位客户,请使用`INSERT TOP INTO SELECT`语句,如下所示: ~~~sql INSERT TOP (10) INTO sales.addresses (street, city, state, zip_code) SELECT street, city, state, zip_code FROM sales.customers ORDER BY first_name, last_name; ~~~ SQL Server返回以下消息,表明已成功插入十行。 ~~~shell (10 rows affected) ~~~ #### 3\. 插入行的百分比 可以在表中插入百分比的行,而不是使用绝对行数。 首先,删除`addresses`表中的所有行: ~~~sql TRUNCATE TABLE sales.addresses; ~~~ 其次,将`customers`表中前`2%`的行按名字和姓氏排序后插入到`addresses`表中: ~~~sql INSERT TOP (10) PERCENT INTO sales.addresses (street, city, state, zip_code) SELECT street, city, state, zip_code FROM sales.customers ORDER BY first_name, last_name; ~~~ SQL Server发出以下消息,指示已成功插入`145`行。 ~~~shell (145 rows affected) ~~~ >[danger] ## 3.5.4 [更新记录] - 更改表中的现有值。 要修改表中的现有数据,请使用以下`UPDATE`语句语法: ~~~sql UPDATE table_name SET c1 = v1, c2 = v2, ... cn = vn [WHERE condition] ~~~ 在上面语法中, * 首先,指定要从中更新数据的表的名称。 * 其次,指定要更新的列`c1`,`c2`,`...`,`cn`和值`v1`,`v2`,`... vn`的列表。 * 第三,在`WHERE`子句中指定条件以选择更新的行。WHERE子句是可选的。 如果不指定`WHERE`子句,则表中的所有行都将更新。 ## SQL Server UPDATE示例 首先,创建一个名为`taxes`的新表。 ~~~sql CREATE TABLE sales.taxes ( tax_id INT PRIMARY KEY IDENTITY (1, 1), state VARCHAR (50) NOT NULL UNIQUE, state_tax_rate DEC (3, 2), avg_local_tax_rate DEC (3, 2), combined_rate AS state_tax_rate + avg_local_tax_rate, max_local_tax_rate DEC (3, 2), updated_at datetime ); ~~~ 其次,执行以下语句将数据插入`taxes`表: INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Alabama',0.04,0.05,0.07); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Alaska',0,0.01,0.07); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Arizona',0.05,0.02,0.05); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Arkansas',0.06,0.02,0.05); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('California',0.07,0.01,0.02); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Colorado',0.02,0.04,0.08); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Connecticut',0.06,0,0); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Delaware',0,0,0); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Florida',0.06,0,0.02); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Georgia',0.04,0.03,0.04); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Hawaii',0.04,0,0); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Idaho',0.06,0,0.03); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Illinois',0.06,0.02,0.04); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Indiana',0.07,0,0); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Iowa',0.06,0,0.01); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Kansas',0.06,0.02,0.04); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Kentucky',0.06,0,0); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Louisiana',0.05,0.04,0.07); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Maine',0.05,0,0); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Maryland',0.06,0,0); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Massachusetts',0.06,0,0); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Michigan',0.06,0,0); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Minnesota',0.06,0,0.01); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Mississippi',0.07,0,0.01); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Missouri',0.04,0.03,0.05); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Montana',0,0,0); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Nebraska',0.05,0.01,0.02); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Nevada',0.06,0.01,0.01); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('New Hampshire',0,0,0); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('New Jersey',0.06,0,0); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('New Mexico',0.05,0.02,0.03); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('New York',0.04,0.04,0.04); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('North Carolina',0.04,0.02,0.02); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('North Dakota',0.05,0.01,0.03); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Ohio',0.05,0.01,0.02); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Oklahoma',0.04,0.04,0.06); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Oregon',0,0,0); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Pennsylvania',0.06,0,0.02); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Rhode Island',0.07,0,0); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('South Carolina',0.06,0.01,0.02); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('South Dakota',0.04,0.01,0.04); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Tennessee',0.07,0.02,0.02); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Texas',0.06,0.01,0.02); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Utah',0.05,0,0.02); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Vermont',0.06,0,0.01); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Virginia',0.05,0,0); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Washington',0.06,0.02,0.03); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('West Virginia',0.06,0,0.01); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Wisconsin',0.05,0,0.01); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('Wyoming',0.04,0.01,0.02); INSERT INTO sales.taxes(state,state\_tax\_rate,avg\_local\_tax\_rate,max\_local\_tax\_rate) VALUES('D.C.',0.05,0,0); #### 1\. 更新所有行示例中的单个列 以下语句更新`taxs`表中所有行的单个列: ~~~sql UPDATE sales.taxes SET updated_at = GETDATE(); ~~~ 在此示例中,语句将`updated_at`列中的值更改为`GETDATE()`函数返回的系统日期时间。 SQL Server发出以下消息: ~~~sql (51 rows affected) ~~~ 这表示有`51`行记录已成功更新。 下面通过以下查询来验证更新结果: ~~~sql SELECT * FROM sales.taxes; ~~~ 从输出中可以清楚地看到,`updated_at`列已使用当前日期值进行更新。 #### 2\. 更新多列示例 对于最高当地税率为`1%`的州,以下语句将最高当地税率提高`2%`,以及平均税率提高`1%`。 ~~~sql UPDATE sales.taxes SET max_local_tax_rate += 0.02, avg_local_tax_rate += 0.01 WHERE max_local_tax_rate = 0.01; ~~~ 以下是SQL Server返回的消息: ~~~shell (7 rows affected) ~~~ 这意味着`7`个州的税收已经更新。 >[danger] ## 3.5.5 [删除记录] - 删除表的一行或多行。 使用delete语句 删除全部:delete from 表名 删除 ID小于100的行: delete from 表名 where ID<100 WHILE 1=1 BEGIN DELETE TOP(100) FROM [Text] where [NAME]='测试bai' IF @@ROWCOUNT<100 BREAK; END delete 表名 where 字段A like '%a%' or 字段A like '%b%' >[danger] ## 3.5.6 [合并记录] 使用单个语句执行插入,更新和删除的混合步骤 假设有两个表名为:`source`表和`target`表,并且需要根据`source`表中匹配的值更新`target`表。 有三种情况: * `source`表有一些`target`表中不存在的行。在这种情况下,需要将`source`表中的行插入到`target`表中。 * `target`表有一些`source`表中不存在的行。 在这种情况下,需要从`target`表中删除行。 * `source`表的某些行具有与`target`表中的行相同的键。 但是,这些行在非键列中具有不同的值。 在这种情况下,需要使用来自`source`表的值更新`target`表中的行。 下图说明了`source`表和`target`表以及相应的操作:插入,更新和删除: ![](https://www.yiibai.com/uploads/article/2019/02/14/143015_15416.png) 如果单独使用`INSERT`,`UPDATE`和`DELETE`语句,则必须构造三个单独的语句,以使用`source`表中的匹配行将数据更新到`target`表。 但是,SQL Server提供`MERGE`语句以用于同时执行三个操作。 以下是`MERGE`语句的语法: ~~~sql MERGE target_table USING source_table ON merge_condition WHEN MATCHED THEN update_statement WHEN NOT MATCHED THEN insert_statement WHEN NOT MATCHED BY SOURCE THEN DELETE; ~~~ 首先,在`MERGE`子句中指定`source_table`表和`target_table`表。 其次,`merge_condition`确定`source_table`表中的行如何与`target_table`表中的行匹配。 它类似于`join`子句中的`join`条件。 通常,使用主键或唯一键的键列进行匹配。 第三,`merge_condition`有三种状态:`MATCHED`,`NOT MATCHED`和`NOT MATCHED BY SOURCE`。 * `MATCHED`:这些是与合并条件匹配的行。 在图中,它们显示为蓝色。 对于匹配的行,需要使用`source_table`表中的值更新`target_table`表中的行列。 * `NOT MATCHED`:这些是`source_table`表中的行,`target_table`表中没有任何匹配的行。 在图中,它们显示为橙色。 在这种情况下,需要将`source_table`表中的行添加到`target_table`表。 请注意,`NOT MATCHED BY TARGET`也称为目标不匹配。 * `NO MATCHED BY SOURCE`:这些是`target_table`表中与`source_table`表中的任何行都不匹配的行。 它们在图中显示为绿色。 如果要将`target_table`表与`source_table`表中的数据同步,则需要使用此匹配条件从`target_table`表中删除行。 ## SQL Server MERGE语句示例 假设有两个表:`sales.category`和`sales.category_staging`,它们按产品类别存储销售额。参考以下创建语句: ~~~sql CREATE TABLE sales.category ( category_id INT PRIMARY KEY, category_name VARCHAR(255) NOT NULL, amount DECIMAL(10 , 2 ) ); INSERT INTO sales.category(category_id, category_name, amount) VALUES(1,'Children Bicycles',15000), (2,'Comfort Bicycles',25000), (3,'Cruisers Bicycles',13000), (4,'Cyclocross Bicycles',10000); CREATE TABLE sales.category_staging ( category_id INT PRIMARY KEY, category_name VARCHAR(255) NOT NULL, amount DECIMAL(10 , 2 ) ); INSERT INTO sales.category_staging(category_id, category_name, amount) VALUES(1,'Children Bicycles',15000), (3,'Cruisers Bicycles',13000), (4,'Cyclocross Bicycles',20000), (5,'Electric Bikes',10000), (6,'Mountain Bikes',10000); ~~~ 要使用`sales.category_staging`(源表)中的值将数据更新到`sales.category`(目标表),请使用以下`MERGE`语句: ~~~sql MERGE sales.category t USING sales.category_staging s ON (s.category_id = t.category_id) WHEN MATCHED THEN UPDATE SET t.category_name = s.category_name, t.amount = s.amount WHEN NOT MATCHED BY TARGET THEN INSERT (category_id, category_name, amount) VALUES (s.category_id, s.category_name, s.amount) WHEN NOT MATCHED BY SOURCE THEN DELETE; ~~~ 执行过程如下图所示 - ![](https://www.yiibai.com/uploads/article/2019/02/14/143758_23597.png) 在此示例中,使用两个表中`category_id`列中的值作为合并条件。 * 首先,`sales.category_staging`表中`id`值为`1`,`3`,`4`的行与目标表中的行匹配,因此,`MERGE`语句更新`sales.category`表中类别名称和`amount`列中的值。 * 其次,`sales.category_staging`表中`id`值为`5`和`6`的行在`sales.category`表中不存在,因此`MERGE`语句将这些行插入到目标表中。 * 第三,`sales.sales_staging`表中不存在`sales.category`表中具有`id`值为`2`的行,因此,`MERGE`语句将删除此行。 在合并的结果中,`sales.category`表中的数据与`sales.category_staging`表中的数据完全同步。