2.

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 に含める扱いが一般的です。

編集
Post Share
子ページ
  1. SELECT文
  2. INSERT文
  3. UPDATE文
  4. DELETE文
  5. WHERE句
  6. JOIN句
  7. 集合演算子
  8. インラインビュー
  9. 副問い合わせ
同階層のページ
  1. DDL
  2. DML
  3. トランザクション制御
  4. データディクショナリ
  5. 動的パフォーマンスビュー
  6. 関数