この内容は古いバージョンです。最新バージョンを表示するには、戻るボタンを押してください。
バージョン:6
ページ更新者:atom
更新日時:2026-06-11 07:07:02

タイトル: DML
SEOタイトル: SQL DML (データ操作言語) 完全ガイド

この記事の要点
  • DML (Data Manipulation Language) はデータを「読み・書き・更新・削除」する命令群: SELECT / INSERT / UPDATE / DELETE
  • DDL との違い: DDL はテーブル構造を変える (CREATE/ALTER/DROP)。DML は中身のデータだけ動かす
  • INSERT のバリエーション: 単純 INSERT / INSERT ... SELECT / INSERT IGNORE / ON DUPLICATE KEY UPDATE / MERGE (UPSERT)
  • UPDATE / DELETE は WHERE 必須。付け忘れで全行更新の事故が発生する
  • TRUNCATE は DDL。DML の DELETE と挙動が違う (高速・ROLLBACK 不可・AUTO_INCREMENT リセット)

DML とは

DML (Data Manipulation Language / データ操作言語) は、テーブル内のデータを操作する SQL コマンド群です。SQL のうち実務で最も使うのが DML で、おおよそ全クエリの 95% を占めます。

コマンド役割頻度
SELECTデータを取り出す(参照)★★★★★
INSERT新しい行を追加★★★★
UPDATE既存行の値を更新★★★★
DELETE行を削除★★★
MERGEUPSERT (存在すれば更新、無ければ挿入)★★

DML / DDL / DCL / TCL の整理

分類用途コマンド例自動コミット
DMLデータ操作SELECT/INSERT/UPDATE/DELETEトランザクション可
DDL構造定義CREATE/ALTER/DROP/TRUNCATE多くの DB で暗黙コミット
DCL権限制御GRANT/REVOKE暗黙コミット
TCLトランザクションBEGIN/COMMIT/ROLLBACK

INSERT の全パターン

-- パターン1: 単純 INSERT
INSERT INTO users (name, email)
VALUES ('田中', 'tanaka@example.com');

-- パターン2: 複数行 INSERT(パフォーマンスが10倍違うことも)
INSERT INTO users (name, email) VALUES
  ('佐藤', 'sato@example.com'),
  ('鈴木', 'suzuki@example.com'),
  ('高橋', 'takahashi@example.com');

-- パターン3: SELECT 結果を INSERT
INSERT INTO users_backup (id, name, email)
SELECT id, name, email FROM users WHERE created_at < '2025-01-01';

-- パターン4: INSERT IGNORE(MySQL)重複キーは無視
INSERT IGNORE INTO users (id, name) VALUES (1, '田中');
-- → id=1 が既存ならエラーにならず何もしない

-- パターン5: ON DUPLICATE KEY UPDATE(MySQL UPSERT)
INSERT INTO daily_counts (date, count) VALUES ('2025-05-18', 1)
ON DUPLICATE KEY UPDATE count = count + 1;

-- パターン6: PostgreSQL の UPSERT
INSERT INTO daily_counts (date, count) VALUES ('2025-05-18', 1)
ON CONFLICT (date) DO UPDATE SET count = daily_counts.count + 1;

-- パターン7: 標準 SQL の MERGE
MERGE INTO daily_counts t
USING (SELECT '2025-05-18'::date AS d, 1 AS c) s
ON t.date = s.d
WHEN MATCHED THEN UPDATE SET count = t.count + s.c
WHEN NOT MATCHED THEN INSERT (date, count) VALUES (s.d, s.c);

UPDATE — 詳細

-- 単純な更新
UPDATE users SET status = 'inactive' WHERE id = 1;

-- 複数列を同時更新
UPDATE users
SET status = 'inactive', updated_at = NOW(), updated_by = 'system'
WHERE last_login_at < NOW() - INTERVAL 1 YEAR;

-- UPDATE JOIN(MySQL): 他テーブルの値で更新
UPDATE orders o
JOIN products p ON o.product_id = p.id
SET o.price_snapshot = p.current_price
WHERE o.created_at >= CURDATE();

-- 同等を PostgreSQL で
UPDATE orders SET price_snapshot = p.current_price
FROM products p
WHERE orders.product_id = p.id
  AND orders.created_at >= CURRENT_DATE;

-- サブクエリで更新
UPDATE users
SET order_count = (SELECT COUNT(*) FROM orders WHERE user_id = users.id);

DELETE — 詳細

-- 条件削除
DELETE FROM logs WHERE created_at < NOW() - INTERVAL 90 DAY;

-- DELETE JOIN(MySQL)
DELETE o FROM orders o
JOIN users u ON o.user_id = u.id
WHERE u.deleted_at IS NOT NULL;

-- PostgreSQL は USING
DELETE FROM orders
USING users
WHERE orders.user_id = users.id AND users.deleted_at IS NOT NULL;

-- LIMIT 付き削除(バッチで小分けに削除する定番)
DELETE FROM logs WHERE created_at < '2024-01-01' LIMIT 1000;
-- ループで回す

DELETE vs TRUNCATE — 似て非なる

項目DELETETRUNCATE
分類DMLDDL
WHERE 句使える使えない(全行削除)
速度遅い(行毎にログ)非常に高速
ROLLBACK多くの DB で不可
AUTO_INCREMENTリセットされないリセットされる
トリガ発火する発火しない
外部キー参照カスケード可多くの DB でエラー

トランザクションで DML を安全に

-- 本番の更新は必ずトランザクション内で
START TRANSACTION;     -- または BEGIN
  UPDATE accounts SET balance = balance - 1000 WHERE id = 1;
  -- 件数チェック
  SELECT ROW_COUNT();  -- 1 でなければ ROLLBACK
  UPDATE accounts SET balance = balance + 1000 WHERE id = 2;
COMMIT;

-- 失敗時
ROLLBACK;

パフォーマンス Tips

  • 大量 INSERT は 複数行 INSERT でラウンドトリップを削減(10〜100 倍速い)
  • 大量 DELETE は LIMIT N で小分けにする(ロック時間短縮)
  • UPDATE は インデックスのある列で WHERE。フルスキャン UPDATE はテーブルロックの危険
  • INSERT 直前の SET autocommit=0; + COMMIT; でログフラッシュ回数を削減
  • UPSERT は INSERT + UPDATE より ON DUPLICATE KEY UPDATE 1 発のほうが速くてアトミック

FAQ

Q: DELETE で消したデータを戻せるか
A: トランザクション中なら ROLLBACK。COMMIT 後はバックアップから復元するしかありません。

Q: UPDATE と REPLACE の違い
A: REPLACE (MySQL) は「DELETE + INSERT」相当で、対象行を一度消してから挿入します。AUTO_INCREMENT が進む / 外部キーで CASCADE が走る等の副作用に注意。

Q: SELECT は DML?
A: SQL 標準では「DQL (Data Query Language) と分けるべき」という説もありますが、実務では DML に含める扱いが一般的です。