SQL ServerのMERGEステートメントは、**1つの操作でデータのINSERT(追加)、UPDATE(更新)、DELETE(削除)**を同時に実行できる強力なSQLコマンドです。
通常、テーブルを更新するときにはINSERT、UPDATE、DELETEをそれぞれ分けて行いますが、MERGEを使うことで、一度のSQLで条件に応じたデータ操作ができるようになります。
例えば、商品管理システムで新しい在庫データが来たときに、既存の商品を更新するか、見つからない商品を新規追加するケースを想像してみてください。
MERGEを使えば、こうした操作を効率的に一括で行うことができます。
MERGEの基本構文
MERGEの基本構文は以下の通りです。
MERGE INTO 対象テーブル AS target
USING 参照テーブル AS source
ON target.キー列 = source.キー列
WHEN MATCHED THEN
-- マッチした場合の処理
UPDATE SET target.列名 = source.列名
WHEN NOT MATCHED THEN
-- マッチしない場合の処理
INSERT (列名1, 列名2, ...) VALUES (source.列名1, source.列名2, ...)
WHEN NOT MATCHED BY SOURCE THEN
-- ソースに存在しないデータの処理
DELETE;
MERGEの使用例
ここでは、2つのテーブルを用いた実際の例を見てみましょう。
- 対象テーブル(Products):現在の在庫情報を持つテーブル
- 参照テーブル(NewStock):新しい在庫データを持つテーブル
テーブルの作成
まず、例で使用するテーブルを作成します。
-- Productsテーブルの作成
CREATE TABLE Products (
ProductID INT PRIMARY KEY,
ProductName VARCHAR(100),
Stock INT
);
-- NewStockテーブルの作成
CREATE TABLE NewStock (
ProductID INT PRIMARY KEY,
ProductName VARCHAR(100),
Stock INT
);
サンプルデータの挿入
-- Productsにデータを挿入
INSERT INTO Products (ProductID, ProductName, Stock)
VALUES (1, 'Laptop', 10),
(2, 'Mouse', 50),
(3, 'Keyboard', 30);
-- NewStockにデータを挿入
INSERT INTO NewStock (ProductID, ProductName, Stock)
VALUES (1, 'Laptop', 15), -- 在庫が更新されるべき
(2, 'Mouse', 50), -- 変わらない
(4, 'Monitor', 20); -- 新規追加されるべき
MERGEを使った処理
上記の2つのテーブルを使い、新しい在庫データに基づいてProductsテーブルを更新します。
MERGE INTO Products AS target
USING NewStock AS source
ON target.ProductID = source.ProductID
WHEN MATCHED THEN
UPDATE SET target.Stock = source.Stock
WHEN NOT MATCHED THEN
INSERT (ProductID, ProductName, Stock)
VALUES (source.ProductID, source.ProductName, source.Stock)
WHEN NOT MATCHED BY SOURCE THEN
DELETE;
- MATCHEDの場合:同じProductIDがある場合、在庫(Stock)を更新
- NOT MATCHEDの場合:参照テーブルに存在するが対象テーブルにない場合、商品を新規追加
- NOT MATCHED BY SOURCEの場合:新しい在庫データに存在しない商品は削除
MERGEのメリットと注意点
メリット
- コードの簡略化:1つのSQLで複数の操作が可能になる。
- パフォーマンスの向上:複数のSQL文を実行するより効率的。
- 管理の容易さ:変更箇所が一箇所にまとまるためメンテナンスが楽。
注意点
- デッドロック:複数のテーブルにアクセスするため、デッドロックが発生する可能性があります。
- トリガーの動作:MERGEがトリガーの動作に影響する場合があるため、注意が必要です。
- NULL処理:条件やデータにNULLが含まれる場合、意図しない結果を生むことがあります。
MERGEを使った演習問題
次の演習では、上記と似たケースを体験します。以下のようなテーブルを用意してください。
演習課題
Employeesテーブル:現在の社員情報を管理するテーブル
CREATE TABLE Employees (
EmployeeID INT PRIMARY KEY,
EmployeeName VARCHAR(100),
Department VARCHAR(50)
);
INSERT INTO Employees (EmployeeID, EmployeeName, Department)
VALUES (1, 'Alice', 'HR'),
(2, 'Bob', 'IT'),
(3, 'Charlie', 'Finance');
NewEmployeesテーブル:新しい社員データを管理するテーブル
CREATE TABLE NewEmployees (
EmployeeID INT PRIMARY KEY,
EmployeeName VARCHAR(100),
Department VARCHAR(50)
);
INSERT INTO NewEmployees (EmployeeID, EmployeeName, Department)
VALUES (1, 'Alice', 'HR'), -- 更新されない
(2, 'Bob', 'Engineering'), -- 部署が更新されるべき
(4, 'Dave', 'Marketing'); -- 新規追加されるべき
課題:上記の2つのテーブルを使い、以下の条件でEmployeesテーブルを更新するMERGE文を作成してください。
- EmployeeIDが一致する場合は部署を更新
- 一致しない場合は新しい社員を追加
- 新しい社員データに存在しない社員は削除
演習問題の解答例
以下は演習問題の解答例です。
MERGE INTO Employees AS target
USING NewEmployees AS source
ON target.EmployeeID = source.EmployeeID
WHEN MATCHED THEN
UPDATE SET target.Department = source.Department
WHEN NOT MATCHED THEN
INSERT (EmployeeID, EmployeeName, Department)
VALUES (source.EmployeeID, source.EmployeeName, source.Department)
WHEN NOT MATCHED BY SOURCE THEN
DELETE;
実行結果
- Aliceのデータは変更なし。
- Bobの部署がITからEngineeringに更新されます。
- Daveが新規追加されます。
- Charlieは新しいデータに存在しないため削除されます。
まとめ
MERGEステートメントは、複数のテーブル操作を1つのクエリで簡潔に行えるため、SQL Serverで非常に便利な機能です。
ただし、使用する際はデッドロックやNULL処理などの注意点も考慮する必要があります。
今回の演習問題を通じて、MERGEの基礎をしっかりと学ぶことができたでしょう。今後のデータベース操作で、効率的に活用してみてください。