SQL
パターン③ MERGE 型 UPDATE — Upsert の決定打 (地雷つき)
出典: SQL Server UPDATE … FROM SELECT 3パターン — 業務SE が JOIN / CTE / MERGE を本番で使い分ける判断軸 — パターン③ MERGE 型 UPDATE — Upsert の決定打 (地雷つき)
-- products に対して、categories マスタの全 id を Upsert
-- (既存 category_id があれば name を更新、なければ INSERT)
MERGE INTO products AS tgt
USING (
SELECT id, name FROM categories WHERE active = 1
) AS src
ON tgt.category_id = src.id
WHEN MATCHED THEN
UPDATE SET tgt.category_name = src.name
WHEN NOT MATCHED BY TARGET THEN
INSERT (category_id, category_name) VALUES (src.id, src.name);
-- ★ WHEN NOT MATCHED BY SOURCE は書かない (障害対応中の鉄則)
▸ この snippet は実行結果未収録
▸ 実行結果は未収録です
Source収録記事
この snippet は記事の「パターン③ MERGE 型 UPDATE — Upsert の決定打 (地雷つき)」セクションに登場する。コードの前後の文脈・ハマりどころの解説は記事本文で。
同じ記事から
4 件-- products テーブルの category_name を categories マスタの最新名で更新 UPDATE p SET p.category_name = c.name FROM products p未収録
パターン① JOIN 型 UPDATE — 単純 1:1 コピーの最短記述
#3c346e6ce0cf
-- 必須プレチェック: 結合元 (categories) に id 重複がないか確認 SELECT id, COUNT(*) AS cnt FROM categories GROUP BY id
▶ 実行可
パターン① JOIN 型 UPDATE — 単純 1:1 コピーの最短記述
#83da9e81c3d9
-- 各 category_id に複数 categories 行がある場合、name の最新 (MAX(updated_at)) を採用 WITH src AS ( SELECT c.id AS category_id,未収録
パターン② CTE 型 UPDATE — 集約反映と可読性の本命
#72cdfe89da29
-- (a) 範囲ロックを早めに取る (UPDATE 1 文で完結する場合) UPDATE T1 WITH (UPDLOCK, HOLDLOCK) SET status = 'fixed' FROM T1 INNER JOIN ... ON ...未収録
並列実行時のロストアップデート — 3 パターン共通の落とし穴
#785286e63e10
