2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

SQL Serverのデータ比較

2
Last updated at Posted at 2026-02-23

はじめに

SQL Server環境で大量データの移行を行いました。

データ移行や改修を行ったあと、必ず必要になるのが データ比較(差分確認) です。

  • 本当に同じデータになっているか
  • 移行漏れはないか
  • 想定外の更新が起きていないか

本記事では、データ比較の手法を整理します。

データ比較の全体像

比較方法は大きく2パターンあります。

  • 同一DB内を比較(SQLで比較)
  • 別DBを比較(ファイル経由で比較)

まずはSQLで比較から見ていきます。

同一DB内のデータ比較

同一DB内の比較であれば、SQLだけで完結します。

完全一致比較(EXCEPT)

-- AにあってBにない
SELECT * FROM tableA
EXCEPT
SELECT * FROM tableB;

-- BにあってAにない
SELECT * FROM tableB
EXCEPT
SELECT * FROM tableA;

主キー比較(NOT EXISTS)

-- AにあってBにない
SELECT * FROM tableA A WHERE NOT EXISTS (SELECT 1 FROM tableB B WHERE B.Id = A.Id)

-- BにあってAにない
SELECT * FROM tableB B WHERE NOT EXISTS (SELECT 1 FROM tableA A WHERE A.Id = B.Id)

EXCEPT と NOT EXISTS の比較

EXCEPT の特徴

  • 行全体を比較して差分を抽出する
  • 両SELECTの列数・型・並びが一致している必要がある
  • 結果は自動的に重複排除(DISTINCT相当)される
  • NULL同士は等しいものとして扱われる

EXCEPT の注意点

  • 重複行の個数差は検出できない(DISTINCT化されるため)
  • 大規模テーブルではパフォーマンスが劣化しやすい
  • 比較対象列を限定したい場合は明示的に列指定が必要

NOT EXISTS の特徴

  • 指定条件で存在有無を判定する
  • 行全体ではなく、WHERE句の条件のみを比較する
  • 重複行はそのまま扱われる
  • 条件を柔軟に書ける

NOT EXISTS の注意点

  • NULLを含む条件では意図しない結果になることがある
  • インデックスが無いと極端に遅くなる

使い分け

  • 完全一致検証 → EXCEPT
  • 列差分検出 → EXCEPT
  • 主キー存在チェック → NOT EXISTS
  • 日次差分抽出 → NOT EXISTS
  • 大規模データ比較 → NOT EXISTS

別DBのデータ比較

  • リンクサーバーが作れない
  • 参照権限が限定的
  • 運用環境で直接JOIN不可

この場合は、ファイル経由比較が現実解になります。

bcpコマンドを使ったデータ比較(bcp → WinMerge)

もっともシンプルで現場採用率が高い方法です。

手順の流れ
ServerA → bcp出力 → ファイルA
ServerB → bcp出力 → ファイルB
↓
WinMergeで比較

手順①:Serverから出力

ServerAから出力
bcp "SELECT * FROM tableA ORDER BY Id" queryout tableA.csv -w -S ServerA -T -d sample_db
ServerBから出力
bcp "SELECT * FROM tableB ORDER BY Id" queryout tableB.csv -w -S ServerB -T -d sample_db

手順②:WinMergeで比較

  • 左:tableA.csv
  • 右:tableB.csv

これで差分を視覚的に確認できます。

実務の重要ポイント

ORDER BY は必ず付ける

並び順が違うだけで、全件差分に見えてしまいます。

文字コードは統一する

日本語を扱う場合は -w(Unicode)推奨

OPENROWSET(BULK)を使ったデータ比較(bcp → クエリ比較)

GUIツールが使えない環境では、SQLで比較する方法もあります。

手順の流れ
ServerA → bcp出力 → CSV
ServerB → bcp出力 → CSV
↓
OPENROWSET(BULK) で差分比較

手順①:Serverから出力

ServerAから出力
bcp "SELECT * FROM tableA ORDER BY Id" queryout tableA.csv -w -t "," -S ServerA -T -d sample_db
ServerBから出力
bcp "SELECT * FROM tableB ORDER BY Id" queryout tableB.csv -w -t "," -S ServerB -T -d sample_db

手順②:差分比較

SELECT * FROM OPENROWSET(
    BULK 'C:\data\tableA.csv',
    DATAFILETYPE = 'widechar',
    FIELDTERMINATOR = ',',
    ROWTERMINATOR = '\n'
) AS tableA
EXCEPT
SELECT * FROM OPENROWSET(
    BULK 'C:\data\tableB.csv',
    DATAFILETYPE = 'widechar',
    FIELDTERMINATOR = ',',
    ROWTERMINATOR = '\n'
) AS tableB

WinMerge と OPENROWSET+EXCEPT の比較

WinMerge の特徴

  • GUIで直感的に差分を確認できる
  • 行単位の違いが視覚的に分かりやすい
  • SQLを書かずに比較できる
  • 小~中規模データの確認に向いている

WinMerge の注意点

  • 行順が違うと全差分扱いになる(ORDER BY必須)
  • 件数が多いと表示や比較が重くなる
  • バッチ化しにくい
  • 列単位の厳密比較には不向き

OPENROWSET+EXCEPT の特徴

  • SQLで差分行を正確に抽出できる
  • バッチやスクリプトに組み込みやすい
  • 大量データでも比較的スケールする
  • 差分件数の把握や後続処理に向いている

OPENROWSET+EXCEPT の注意点

  • 列数・型・順序が一致している必要がある
  • EXCEPTは重複行の件数差を検出できない

使い分け

  • 目視確認 → WinMerge
  • 差分抽出・件数確認 → OPENROWSET+EXCEPT
  • 本番検証や定期チェック → OPENROWSET+EXCEPT
  • スポット調査 → WinMerge

まとめ

データ移行や改修後の検証では、データ比較(差分確認) が品質を担保する最後の砦になります。
重要なのは、目的と環境に応じて比較手法を使い分けることです。

同一DB内の比較

  • 完全一致の検証 → EXCEPT
  • 主キー存在チェックや日次差分 → NOT EXISTS

別DB間の比較

  • 目視確認・スポット調査 → bcp & WinMerge
  • 厳密比較・自動化 → bcp & OPENROWSET + EXCEPT

迷ったときのシンプル判断

  • まず目で見たい → WinMerge
  • 差分を正確に取りたい → EXCEPT / NOT EXISTS
  • 定期検証・自動化 → OPENROWSET + EXCEPT

本記事の手法をベースに、現場の制約に合わせて最適な比較フローを組み立てて頂ければ幸いです。


これらの手法でデータ移行をしました。

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?