>[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`表中的数据完全同步。
- 第三章-数据库
- 3.1 SQL Server简介及安装
- 3.2 SQL Server示例数据库
- 3.3 SQL Server 加载示例
- 3.3 SQL Server 中的数据类型
- 3.4 SQL Server 数据定义语言DDL
- 3.5 SQL Server 修改数据
- 3.6 SQL Server 查询数据
- 3.7 SQL Server 连表
- 3.8 SQL Server 数据分组
- 3.9 SQL Server 子查询
- 3.10.1 SQL Server 集合操作符
- 3.10.2 SQL Server聚合函数
- 3.10.3 SQL Server 日期函数
- 3.10.4 SQL Server 字符串函数