>[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;
~~~
執行上面查詢語句,得到以下結果:

#### 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'
);
~~~
執行上面查詢語句,得到以下輸出結果:

#### 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發出以下錯誤:

要為標識列插入顯式值,必須首先執行以下語句:
~~~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)
~~~
通過執行以下查詢來驗證插入數據:

>[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;
~~~
執行上面查詢語句,得到以下結果:

#### 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`表以及相應的操作:插入,更新和刪除:

如果單獨使用`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;
~~~
執行過程如下圖所示 -

在此示例中,使用兩個表中`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 字符串函數