0
0

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で管理するのが実務では強い

0
Last updated at Posted at 2026-03-25

はじめに

この記事では、テストデータを効率良く作る方法として、SQL で管理するやり方を整理します。

結論を先に書くと、手動検証やバッチ検証では、テストデータ作成を SQL に寄せた方が扱いやすいことが多いです。

特に次のような場面を対象にしています。

  • バッチの手動検証をしたい
  • 既存データを消して毎回同じ状態を作りたい
  • 複数テーブルにまたがる前提データをまとめて用意したい
  • 新規テーブルの検証なので、テーブル作成から入れたい

テストデータ作成の方法はいくつかあります。

  • 管理画面から手で登録する
  • アプリの Seeder を使う
  • テストコード内でデータを作る
  • SQL を直接流す

どれも使いどころはあります。

ただし、用途によって向き不向きはあります。

大量データの編集や表形式での管理なら、CSV や TSV の方が扱いやすい場面もあります。

一方で、手動検証や DB 状態確認を伴う実務では、SQL がかなり強い選択肢になります。

先に結論

効率良くテストデータを作りたいなら、次の形で SQL を管理するのがおすすめです。

  1. 変数や対象期間を最初に定義する
  2. 既存データを削除する
  3. 必要ならテーブル作成も入れる
  4. マスタや前提データを投入する
  5. テストケースごとのデータを投入する
  6. 最後に確認用の SELECT を入れる

つまり、単なる INSERT 集ではなく、「どの環境でも流し込める再現用スクリプト」として SQL を作るのが重要です。

先に使い分けを書く

先に書いておくと、常に SQL が最適だと言いたいわけではありません。

テストデータ管理には、CSV や TSV が向いている場面もあります。

例えば次のような点では、CSV や TSV はかなり強いです。

  • 大量データをまとめて扱いやすい
  • 表形式で編集しやすい
  • 列追加や列削除に追従しやすい
  • 非エンジニアでも触りやすい

特に「データそのものを管理する」「件数の多い初期データを流し込む」という観点では、CSV や TSV の方が自然です。

一方で、この記事で扱いたいのは、状態を再現するためのテストデータです。

この用途では、次のように考えると整理しやすいです。

  • SQL は状態を作るスクリプト
  • CSV や TSV は状態のスナップショット

この違いがあるため、SQL には CSV や TSV にはない強みがあります。

なぜ SQL が強いのか

自分は、少なくとも実務の手動検証では、テストデータ作成は SQL がかなり強いと考えています。

理由は次のとおりです。

  • DB に最も近い形で書ける
  • 実際に入るデータをそのまま確認できる
  • 複数テーブルの整合を一気に作れる
  • アプリ実装に依存しにくい
  • どの環境でも流し込みやすい

ここでいう「どの環境でも流し込みやすい」というのは、プログラミング言語の実装に依存しにくいという意味です。

例えば次のような場面でも同じ SQL を使いやすいです。

  • ローカル環境
  • 検証環境
  • ステージング環境
  • 手元の DB クライアント
  • CI で立ち上げた一時 DB

もちろん、DB 製品ごとの差分はあります。

ただ、それでもアプリの Seeder や専用スクリプトよりは「DB に直接流せる形」で共有しやすいことが多いです。

この性質は実務ではかなり重要です。

例えば、ローカルでは流せるが検証環境ではアプリ起動手順が違って使えない、という状況はよくあります。

SQL なら、接続先さえあれば同じ内容をそのまま流しやすいため、環境差分の影響を受けにくくなります。

例えば、Go の Seeder や Java の初期化コードでテストデータを作ると、次の問題が起きやすいです。

  • アプリが起動しないと使えない
  • ORM の書き方に引っ張られる
  • DB の状態を直接見たいときに遠回りになる
  • 他メンバーが SQL ではなくコードを読まないといけない

一方、SQL なら DB を見る人にとって自然です。

特に、バックエンド、QA、DB を見るメンバーが混ざる現場では強いです。

SQL は意図をデータと一緒に持てる

SQL の強みは、単にデータを入れられることではありません。

そのデータが何のためにあるのかを、一緒に残せることです。

例えば次のような形です。

-- ケース1: 本人確認済み + 高額入金ユーザー
INSERT INTO users (id, status, kyc_status)
VALUES (1, 'active', 'verified');

この形なら、データの意味がそのまま残ります。

一方、CSV はデータ自体は見やすいですが、その1行が何のケースなのかは別で管理しないと分かりにくくなります。

id,status,kyc_status
1,active,verified

テストデータでは「この行は何を検証するためのものか」が重要なので、この差は小さくありません。

SQL は前処理と後処理を一体で書ける

SQL は、投入だけでなく前処理と後処理も同じファイルにまとめられます。

例えば次のような形です。

DELETE FROM users;

-- ケース投入
INSERT INTO users (id, status, kyc_status)
VALUES (1, 'active', 'verified');

-- 検証
SELECT *
FROM users
WHERE id = 1;

この形にしておくと、削除、投入、確認までを1ファイルで完結できます。

これは単なるデータファイルではなく、状態再現用のスクリプトとして扱える、ということです。

SQL は依存関係や条件も表現しやすい

テストデータでは、値があるだけでは足りないことがあります。

例えば次のような条件です。

  • 外部キー順序を守りたい
  • UPDATE 前提の初期状態を作りたい
  • 既存データと突き合わせたい
  • 条件ごとにケースを分けたい

こうした場面では、CSV や TSV だけだと表現が足りません。

SQL なら、削除順序、投入順序、条件付き更新、確認用 SELECT まで含めて書けます。

既存データ削除から入れた方がよい

ここはかなり重要です。

テストデータ SQL は、最初に既存データ削除から入れた方が再現性が上がります。

例えば、INSERT だけを並べた SQL は最初の1回は動いても、2回目以降につらくなります。

  • 一意制約に引っかかる
  • 前回データが残っていて件数が変わる
  • update 検証なのか insert 検証なのか分からなくなる

そのため、まずは対象データを消してから作る方が安定します。

DELETE FROM order_summary
WHERE user_id IN ('TEST001', 'TEST002')
  AND target_month = '2026-03-01';

DELETE FROM orders
WHERE user_id IN ('TEST001', 'TEST002', 'TEST003');

この形にしておくと、何回流しても同じ状態を作りやすくなります。

テストデータSQLは「毎回同じ状態を作れるか」が重要

実務で重要なのは、データを作れることではなく、同じ状態を何回でも再現できることです。

例えばバッチ検証では、次の流れを何度もやります。

  1. データを作る
  2. バッチを動かす
  3. 結果を見る
  4. 条件を変える
  5. もう一度試す

このとき、前回データが残っていると比較しにくくなります。

だからこそ、SQL は次の順にした方がよいです。

  • 削除
  • 投入
  • 確認

単純ですが、この形が一番壊れにくいです。

変数定義を最初に置く

今回の SQL ファイルでも良かったのは、最初に変数や対象期間を定義している点です。

これはかなり実務的です。

SET @target_date = '2026-03-01';
SET @next_date = DATE_ADD(@target_date, INTERVAL 1 MONTH);
SET @test_user_1 = 'TEST001';
SET @test_user_2 = 'TEST002';

変数を使う利点は次のとおりです。

  • 同じ ID や日付を何度も直さなくて済む
  • ケースの意図が分かりやすい
  • 月次バッチのような期間条件を書き換えやすい

特に日付系の検証では、変数化しておかないと修正漏れが起きやすいです。

ユーザー変数には文字コード指定も入れる

ユーザー変数(@ 変数)は、代入時の接続セッションの collation を保持します。

テーブル側の列と collation が一致していないと、次のエラーが出ることがあります。

Illegal mix of collations

例えば、リテラルなら通るのに @ 変数を使うと失敗するケースがあります。

詳しい仕組みは「MySQLでリテラルは通るのにユーザー変数でIllegal mix of collationsが出る理由」を参照してください。

対処は、変数定義の前に SET NAMES を1行入れるだけです。

-- 接続の文字コードと collation をテーブルに合わせる
SET NAMES utf8mb4 COLLATE utf8mb4_general_ci;

SET @target_date = '2026-03-01';
SET @test_user_1 = 'TEST001';

テストデータ SQL は Workbench やターミナルなど、複数の接続ツールから流すことがあります。

接続ツールによって collation の初期値が変わることがあるため、先頭に入れておくと安全です。

ケースごとにコメントを書く

テストデータ SQL は、単なるデータ投入ではなく検証仕様の一部です。

そのため、ケースごとにコメントを書いた方が読みやすくなります。

例えば次のような形です。

INSERT INTO orders (order_id, user_id, order_date, status)
VALUES
-- ケースA: 当月注文。集計対象
('ORD001', @test_user_1, DATE_ADD(@target_date, INTERVAL 1 DAY), 'completed'),

-- ケースB: 翌月注文。集計対象外
('ORD002', @test_user_1, DATE_ADD(@next_date, INTERVAL 1 DAY), 'completed'),

-- ケースC: キャンセル済み。集計対象外
('ORD003', @test_user_2, DATE_ADD(@target_date, INTERVAL 2 DAY), 'canceled');

これをやっておくと、後から見ても「なぜこのデータがあるのか」が分かります。

新規テーブルならテーブル作成も同じSQLに入れてよい

新規に作成するテーブルの検証なら、テーブルがない場合は作成 SQL も同じファイルに入れてよいと思います。

むしろ、その方が分かりやすいことがあります。

例えば次のような形です。

CREATE TABLE IF NOT EXISTS order_summary (
  user_id VARCHAR(20) NOT NULL,
  target_month DATE NOT NULL,
  order_count INT NOT NULL,
  created_at DATETIME NOT NULL,
  updated_at DATETIME NOT NULL,
  PRIMARY KEY (user_id, target_month)
);

この形の利点は次のとおりです。

  • 新規参加者でもそのまま流せる
  • 手元 DB にテーブルがない状態から始められる
  • 検証用テーブルの前提が明確になる

ただし、既存本番テーブルの正式な DDL 管理とは分けるべきです。

ここで入れるのは、あくまで検証や再現に必要な最低限の DDL です。

DDL と DML を同じファイルに入れるときの考え方

新規テーブル検証では、次のようにまとめると扱いやすいです。

  1. CREATE TABLE IF NOT EXISTS
  2. DELETE
  3. INSERT
  4. SELECT

例えば次の流れです。

CREATE TABLE IF NOT EXISTS test_orders (
  id BIGINT PRIMARY KEY,
  user_id VARCHAR(20) NOT NULL,
  order_date DATE NOT NULL
);

DELETE FROM test_orders WHERE user_id IN ('TEST001', 'TEST002');

INSERT INTO test_orders (id, user_id, order_date)
VALUES
  (1, 'TEST001', '2026-03-01'),
  (2, 'TEST002', '2026-03-02');

SELECT * FROM test_orders WHERE user_id IN ('TEST001', 'TEST002');

このくらい素直な構成の方が、実務では読みやすいです。

SQLだけでなく最後に確認用SELECTも入れる

投入して終わりではなく、最後に確認用 SELECT を入れるのも大事です。

これは地味ですが、かなり効きます。

SELECT *
FROM order_summary
WHERE user_id IN ('TEST001', 'TEST002')
  AND target_month = '2026-03-01';

これがあると、次の点が楽になります。

  • 投入結果をすぐ確認できる
  • バッチ実行前の状態を見られる
  • 他の人が流しても期待状態を把握しやすい

管理画面や Seeder より SQL が向いている場面

もちろん、管理画面や Seeder、CSV や TSV が不要という話ではありません。

ただし、次の場面では SQL の方がかなり強いです。

  • 月次バッチや集計バッチの検証
  • 境界値を含むデータ作成
  • 複数テーブルの整合を明示したい場合
  • update 前提の初期値をわざと入れたい場合
  • DB を直接見ながら確認したい場合

例えば、集計結果が update されることを確認したいなら、先にわざと不正な値を入れておく、というやり方ができます。

INSERT INTO order_summary (user_id, target_month, order_count, created_at, updated_at)
VALUES ('TEST001', '2026-03-01', 99, NOW(), NOW());

このような「実行前にあえて 99 を入れておく」検証は、SQL の方が意図を表現しやすいです。

SQLで管理するときの注意点

便利ですが、雑に書くと逆に読みづらくなります。

注意点は次のとおりです。

  • 何を検証するデータかコメントを書く
  • 削除対象を広げすぎない
  • 変数で意味を持たせる
  • 本番用 DDL 管理と検証用 SQL を混ぜすぎない
  • 最後に確認用 SELECT を付ける

特に DELETE は危険なので、対象を絞った方がよいです。

おすすめのテンプレート

実務では、次のテンプレートから始めると作りやすいです。

-- 0. 文字コード指定
SET NAMES utf8mb4 COLLATE utf8mb4_general_ci;

-- 1. 変数定義
SET @target_date = '2026-03-01';
SET @test_id_1 = 'TEST001';

-- 2. 必要ならDDL
CREATE TABLE IF NOT EXISTS sample_table (
  id BIGINT PRIMARY KEY,
  user_id VARCHAR(20) NOT NULL
);

-- 3. 事前クリーンアップ
DELETE FROM sample_result WHERE user_id = @test_id_1;
DELETE FROM sample_table WHERE user_id = @test_id_1;

-- 4. 前提データ投入
INSERT INTO sample_result (user_id, count_value)
VALUES (@test_id_1, 99);

-- 5. テストデータ投入
INSERT INTO sample_table (id, user_id)
VALUES (1, @test_id_1);

-- 6. 確認
SELECT * FROM sample_table WHERE user_id = @test_id_1;
SELECT * FROM sample_result WHERE user_id = @test_id_1;

この並びにしておくと、読み手も流れを追いやすいです。

まとめ

効率良くテストデータを作りたいなら、用途ごとに管理方法を分けて考えるのが大事です。

特に次の整理が重要です。

  • CSV や TSV はデータ管理や編集に強い
  • SQL は意図、手順、再現性に強い

そのうえで、手動検証やバッチ検証では SQL がかなり強いです。

特に重要なのは次の点です。

  • INSERT だけでなく、既存データ削除から入れる
  • 変数を最初に定義する
  • ケースごとにコメントを書く
  • 必要ならテーブル作成も同じ SQL に入れる
  • 最後に確認用 SELECT を付ける
  • ローカル、検証環境、ステージングでも同じ SQL を流しやすい形にする

テストデータ作成は、単にデータを入れる作業ではありません。

毎回同じ状態を再現できることが大事です。

その意味で、SQL を「再現用スクリプト」として管理すると、手動検証もチーム共有もしやすくなります。

特にテストデータでは、「なぜこのデータが必要か」をコードとして残せる点に価値があります。

0
0
2

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?