データベースを使っていると、「間違って登録したデータを削除したい」「古い情報を整理したい」という場面が必ずありますよね。
そんなときに使うのが「DELETE文」です。
でも、DELETE文はとても強力な命令なので、使い方を間違えると大切なデータをすべて失ってしまう危険があります。
この記事では、DELETE文を安全に使うための方法を、初心者の方でもわかるように丁寧に説明します。
この記事で学べること
- DELETE文の基本的な使い方
- 安全にデータを削除する方法
- よくある間違いとその対策
- DELETE文を使うときの重要な注意点
一緒に安全なデータ削除の方法を学んでいきましょう!
DELETE文とは何か?

DELETE文の基本的な役割
DELETE文は、データベースのテーブルから「特定の行(レコード)」を削除するためのSQL命令です。
重要なポイント
- 削除されるのは「行」であり、テーブル全体ではありません
- 削除されたデータは基本的に復元できません
- 条件を指定しないと、すべてのデータが削除されてしまいます
サンプルテーブルで理解しよう
以下のようなusersテーブルがあるとします:
usersテーブル
id | name | age | city | status |
---|---|---|---|---|
1 | 田中太郎 | 25 | Tokyo | active |
2 | 佐藤花子 | 30 | Osaka | inactive |
3 | 鈴木一郎 | 35 | Tokyo | active |
4 | 山田美咲 | 28 | Kyoto | inactive |
5 | 高橋健太 | 32 | Tokyo | active |
DELETE文の基本構文
DELETE FROM テーブル名 WHERE 条件;
各部分の説明
DELETE FROM
:「〜から削除する」という意味テーブル名
:削除対象のテーブル名WHERE 条件
:どの行を削除するかの条件
具体的な削除例
特定のユーザーを削除
DELETE FROM users WHERE id = 2;
この命令を実行すると:
実行後のusersテーブル
id | name | age | city | status |
---|---|---|---|---|
1 | 田中太郎 | 25 | Tokyo | active |
3 | 鈴木一郎 | 35 | Tokyo | active |
4 | 山田美咲 | 28 | Kyoto | inactive |
5 | 高橋健太 | 32 | Tokyo | active |
佐藤花子さん(id=2)の行だけが削除されました。
DELETE文とDROP文の違い
初心者がよく混同するコマンドの違いを理解しておきましょう:
命令 | 削除対象 | 例 |
---|---|---|
DELETE | テーブル内の行 | DELETE FROM users; |
DROP | テーブル全体 | DROP TABLE users; |
- DELETE:データだけを削除、テーブル構造は残る
- DROP:テーブル自体を削除、構造もデータもすべて消える
DELETE文の基本がわかったところで、安全に使うための条件指定を学びましょう。
WHERE句で安全に削除対象を指定しよう

WHERE句の重要性
DELETE文で最も重要なのがWHERE句です。これがないと、テーブル内のすべてのデータが削除されてしまいます。
危険な例(WHERE句なし)
DELETE FROM users; -- 全データが削除される!
安全な例(WHERE句あり)
DELETE FROM users WHERE id = 3; -- 特定のデータのみ削除
基本的な条件指定
特定の値で削除
-- ID番号で削除
DELETE FROM users WHERE id = 4;
-- 名前で削除
DELETE FROM users WHERE name = '山田美咲';
-- ステータスで削除
DELETE FROM users WHERE status = 'inactive';
数値の比較
-- 30歳以上のユーザーを削除
DELETE FROM users WHERE age >= 30;
-- 25歳未満のユーザーを削除
DELETE FROM users WHERE age < 25;
文字列の検索
-- 東京以外のユーザーを削除
DELETE FROM users WHERE city != 'Tokyo';
-- 名前に「田」が含まれるユーザーを削除
DELETE FROM users WHERE name LIKE '%田%';
複数条件での削除
AND演算子:すべての条件を満たす
-- 30歳以上かつ非アクティブなユーザーを削除
DELETE FROM users WHERE age >= 30 AND status = 'inactive';
OR演算子:いずれかの条件を満たす
-- 大阪または京都在住のユーザーを削除
DELETE FROM users WHERE city = 'Osaka' OR city = 'Kyoto';
複雑な条件
-- 30歳以上の非アクティブユーザー、または25歳未満のユーザーを削除
DELETE FROM users WHERE (age >= 30 AND status = 'inactive') OR age < 25;
削除前の確認(とても重要!)
DELETE文を実行する前に、必ずSELECT文で対象データを確認しましょう:
ステップ1:削除対象を確認
-- 削除予定のデータを事前確認
SELECT * FROM users WHERE status = 'inactive';
確認結果
id | name | age | city | status
---|----------|-----|--------|--------
2 | 佐藤花子 | 30 | Osaka | inactive
4 | 山田美咲 | 28 | Kyoto | inactive
ステップ2:内容を確認してから削除実行
-- 確認後、削除を実行
DELETE FROM users WHERE status = 'inactive';
ステップ3:削除結果を確認
-- 削除後の状態を確認
SELECT * FROM users;
日付での削除
古いデータの削除
-- 2023年以前の注文データを削除
DELETE FROM orders WHERE order_date < '2024-01-01';
-- 1週間以上前のログを削除
DELETE FROM access_logs WHERE created_at < DATE_SUB(NOW(), INTERVAL 7 DAY);
-- 特定の期間のデータを削除
DELETE FROM temp_data WHERE created_at BETWEEN '2024-01-01' AND '2024-01-31';
削除件数の確認
DELETE文を実行した後は、何件のデータが削除されたかを確認できます:
DELETE FROM users WHERE age > 50;
-- 結果: Query OK, 3 rows affected (0.01 sec)
「3 rows affected」は3件のデータが削除されたことを意味します。
WHERE句を正しく使うことで、必要なデータだけを安全に削除できます。次は、全削除の危険性について詳しく学びましょう。
全行削除の危険性と対策
全行削除とは何か?
WHERE句を付けずにDELETE文を実行すると、テーブル内のすべてのデータが削除されます。
これを「全行削除」と呼びます。
危険な全行削除の例
DELETE FROM users; -- すべてのユーザーデータが削除される
DELETE FROM orders; -- すべての注文データが削除される
DELETE FROM products; -- すべての商品データが削除される
全行削除が起こりやすい場面
1. WHERE句の書き忘れ
-- 意図:非アクティブユーザーのみ削除
-- 実際:WHERE句を書き忘れて全削除
DELETE FROM users; -- 危険!
2. 条件の書き間違い
-- 意図:特定のユーザーを削除
-- 実際:存在しない条件なので何も削除されない(まだマシ)
DELETE FROM users WHERE id = 999999; -- 該当なし
-- より危険:条件が常に真になる
DELETE FROM users WHERE 1 = 1; -- 全削除と同じ!
3. 変数の値が空の場合
-- 変数が空だと意図しない結果に
SET @user_id = '';
DELETE FROM users WHERE id = @user_id; -- 予期しない動作
安全対策1:必ず事前確認する
確認→削除の手順を必ず守る
-- ステップ1:削除対象を必ず確認
SELECT COUNT(*) FROM users WHERE status = 'inactive';
-- 結果: 削除予定件数が表示される
-- ステップ2:具体的な内容も確認
SELECT id, name, status FROM users WHERE status = 'inactive';
-- 結果: 削除される具体的なデータを確認
-- ステップ3:確認後に削除実行
DELETE FROM users WHERE status = 'inactive';
安全対策2:LIMIT句を使用する
大量削除の場合は、LIMIT句で件数を制限できます:
-- 一度に最大10件まで削除
DELETE FROM old_logs WHERE created_at < '2024-01-01' LIMIT 10;
-- 段階的に削除する場合
DELETE FROM large_table WHERE status = 'obsolete' LIMIT 1000;
安全対策3:トランザクションを使用する
トランザクションを使えば、間違いに気づいたときに取り消すことができます:
-- トランザクション開始
START TRANSACTION;
-- 削除を実行
DELETE FROM users WHERE status = 'inactive';
-- 結果を確認(この時点ではまだ確定していない)
SELECT COUNT(*) FROM users;
-- 問題なければ確定
COMMIT;
-- 問題があれば取り消し
-- ROLLBACK;
安全対策4:バックアップの活用
削除前のバックアップ
-- 削除前にデータをバックアップテーブルに保存
CREATE TABLE users_backup AS SELECT * FROM users WHERE status = 'inactive';
-- 確認後に削除実行
DELETE FROM users WHERE status = 'inactive';
-- 問題があれば復元
-- INSERT INTO users SELECT * FROM users_backup;
データベース設定での安全対策
SQL_SAFE_UPDATESの有効化
-- 安全モードを有効にする(MySQL)
SET sql_safe_updates = 1;
-- この設定により、WHERE句なしのDELETEはエラーになる
DELETE FROM users; -- エラー:WHERE句が必要
全行削除してしまった場合の対処法
もし誤って全削除してしまった場合:
- すぐに作業を停止する
- バックアップから復元する
- バイナリログから復旧する(MySQL)
- データベース管理者に連絡する
-- バックアップからの復元例
SOURCE backup_file.sql;
-- 特定の時点まで復旧
mysqlbinlog --stop-datetime="2025-06-03 14:30:00" binlog.000001 | mysql
全行削除は取り返しのつかない事故につながります。必ず事前確認と安全対策を徹底しましょう。
DELETEとTRUNCATEの違いを理解しよう

TRUNCATEとは何か?
TRUNCATE文も、テーブルからデータを削除する命令ですが、DELETE文とは動作が大きく異なります。
TRUNCATE文の基本構文
TRUNCATE TABLE テーブル名;
主な違いの比較
項目 | DELETE | TRUNCATE |
---|---|---|
WHERE句 | 使用可能(条件指定可) | 使用不可(全削除のみ) |
削除速度 | 比較的遅い | 非常に高速 |
ログ記録 | 詳細に記録される | 最小限の記録 |
ロールバック | 可能 | 一部データベースで不可 |
自動増分ID | リセットされない | リセットされる |
外部キー制約 | チェックされる | エラーになる場合あり |
トリガー | 実行される | 実行されない |
具体的な違いを見てみよう
サンプルテーブル:test_users
id | name | created_at |
---|---|---|
1 | ユーザー1 | 2025-06-01 10:00:00 |
2 | ユーザー2 | 2025-06-02 11:00:00 |
3 | ユーザー3 | 2025-06-03 12:00:00 |
DELETEで全削除
DELETE FROM test_users;
-- 新しいデータを挿入
INSERT INTO test_users (name) VALUES ('新ユーザー');
-- 結果:自動増分IDは続きから
-- id=4, name='新ユーザー'
TRUNCATEで全削除
TRUNCATE TABLE test_users;
-- 新しいデータを挿入
INSERT INTO test_users (name) VALUES ('新ユーザー');
-- 結果:自動増分IDがリセット
-- id=1, name='新ユーザー'
それぞれの使い分け
DELETEを使う場面
-- 条件付きでデータを削除したい
DELETE FROM users WHERE last_login < '2024-01-01';
-- ログを残したい
DELETE FROM temp_data WHERE processed = true;
-- 外部キー制約があるテーブル
DELETE FROM orders WHERE order_date < '2024-01-01';
-- トリガーを実行したい
DELETE FROM audit_table WHERE created_at < '2024-01-01';
TRUNCATEを使う場面
-- テーブル全体を高速でクリアしたい
TRUNCATE TABLE temporary_import_data;
-- 自動増分IDをリセットしたい
TRUNCATE TABLE sequence_test;
-- 大量データの全削除(パフォーマンス重視)
TRUNCATE TABLE big_log_table;
-- テストデータの初期化
TRUNCATE TABLE test_data;
実行時間の違い
大量データでの比較例
-- 100万件のデータがあるテーブルの場合
-- DELETE:数十秒〜数分
DELETE FROM large_table;
-- TRUNCATE:数秒
TRUNCATE TABLE large_table;
注意すべきポイント
1. TRUNCATEは取り消しが難しい
-- トランザクション内でも、データベースによっては取り消せない
START TRANSACTION;
TRUNCATE TABLE important_data; -- 一部DBでは即座に確定される
ROLLBACK; -- 取り消せない場合がある
2. 外部キー制約がある場合
-- 親テーブルをTRUNCATEしようとするとエラー
TRUNCATE TABLE users; -- エラー:外部キーで参照されている
-- 解決方法1:外部キー制約を一時的に無効化
SET FOREIGN_KEY_CHECKS = 0;
TRUNCATE TABLE users;
SET FOREIGN_KEY_CHECKS = 1;
-- 解決方法2:DELETEを使用
DELETE FROM users;
3. 権限の違い
-- DELETEに必要な権限
GRANT DELETE ON database.table TO user;
-- TRUNCATEに必要な権限(より強い権限が必要)
GRANT DROP ON database.table TO user;
実用的な選択指針
こんなときはDELETE
- 一部のデータだけを削除したい
- ログや監査が重要
- 外部キー制約がある
- トリガーの実行が必要
- ロールバックの可能性がある
こんなときはTRUNCATE
- テーブル全体をクリアしたい
- 処理速度を重視する
- 自動増分IDをリセットしたい
- テスト環境でのデータリセット
- 一時的なテーブルの初期化
適切な使い分けにより、効率的で安全なデータ削除ができるようになります。
よくあるエラーと対処法

外部キー制約エラー
DELETE文を実行するときに最もよく遭遇するのが、外部キー制約違反のエラーです。
エラーメッセージの例
ERROR 1451 (23000): Cannot delete or update a parent row:
a foreign key constraint fails
発生する状況
-- usersテーブル(親)
| id | name |
|----|----------|
| 1 | 田中太郎 |
| 2 | 佐藤花子 |
-- ordersテーブル(子)
| id | user_id | product |
|----|---------|----------|
| 1 | 1 | 商品A |
| 2 | 1 | 商品B |
| 3 | 2 | 商品C |
-- このDELETEはエラーになる
DELETE FROM users WHERE id = 1; -- 注文データが残っているため
対処法1:子データから先に削除
-- 先に注文データを削除
DELETE FROM orders WHERE user_id = 1;
-- その後でユーザーを削除
DELETE FROM users WHERE id = 1;
対処法2:結合削除(JOIN DELETE)
-- 関連するデータを一度に削除
DELETE users, orders
FROM users
JOIN orders ON users.id = orders.user_id
WHERE users.id = 1;
対処法3:CASCADE設定の活用
-- テーブル作成時にCASCADE設定
CREATE TABLE orders (
id INT PRIMARY KEY,
user_id INT,
product VARCHAR(100),
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
-- 親データを削除すると、子データも自動削除される
DELETE FROM users WHERE id = 1; -- 関連する注文も自動削除
権限不足エラー
エラーメッセージの例
ERROR 1142 (42000): DELETE command denied to user 'username'@'host'
対処法
-- 管理者として権限を付与
GRANT DELETE ON database_name.table_name TO 'username'@'host';
-- または、より広い権限を付与
GRANT ALL PRIVILEGES ON database_name.* TO 'username'@'host';
-- 権限の確認
SHOW GRANTS FOR 'username'@'host';
WHERE句の条件ミス
よくある間違い1:データ型の不一致
-- 間違い:数値を文字列として比較
DELETE FROM users WHERE id = "1"; -- 動作するが非効率
-- 正しい:適切なデータ型で比較
DELETE FROM users WHERE id = 1;
よくある間違い2:NULL値の扱い
-- 間違い:NULLは = では比較できない
DELETE FROM users WHERE last_login = NULL; -- 何も削除されない
-- 正しい:IS NULLを使用
DELETE FROM users WHERE last_login IS NULL;
よくある間違い3:大文字小文字の区別
-- データベース設定によっては区別される
DELETE FROM users WHERE name = 'tanaka'; -- 'Tanaka'は削除されない
-- 確実な方法:LOWER関数を使用
DELETE FROM users WHERE LOWER(name) = LOWER('Tanaka');
パフォーマンス関連の問題
問題:大量データの削除が遅い
-- 非効率:WHERE句にインデックスがない
DELETE FROM large_table WHERE created_at < '2024-01-01'; -- 遅い
対処法1:インデックスの確認
-- インデックスの存在確認
SHOW INDEX FROM large_table;
-- 必要に応じてインデックス作成
CREATE INDEX idx_created_at ON large_table(created_at);
対処法2:バッチ削除
-- 一度に大量削除せず、小分けにする
DELETE FROM large_table WHERE created_at < '2024-01-01' LIMIT 1000;
-- バッチ処理の例
REPEAT
DELETE FROM large_table WHERE created_at < '2024-01-01' LIMIT 1000;
UNTIL ROW_COUNT() = 0 END REPEAT;
デッドロック エラー
エラーメッセージの例
ERROR 1213 (40001): Deadlock found when trying to get lock
対処法1:リトライ機能の実装
-- アプリケーション側でリトライ処理
DELIMITER //
CREATE PROCEDURE safe_delete(IN user_id INT)
BEGIN
DECLARE attempts INT DEFAULT 0;
DECLARE done INT DEFAULT 0;
retry_loop: LOOP
BEGIN
DECLARE CONTINUE HANDLER FOR 1213
BEGIN
SET attempts = attempts + 1;
IF attempts >= 3 THEN
LEAVE retry_loop;
END IF;
END;
DELETE FROM users WHERE id = user_id;
SET done = 1;
LEAVE retry_loop;
END;
END LOOP;
END //
DELIMITER ;
対処法2:トランザクションの最適化
-- 短いトランザクションにする
START TRANSACTION;
DELETE FROM users WHERE id = 1; -- 素早く実行
COMMIT;
-- 長時間のロックを避ける
-- 時間のかかる処理は事前に準備
削除件数の確認エラー
問題:予期しない件数が削除された
-- 意図:1件のみ削除のつもり
DELETE FROM users WHERE name LIKE '%田中%'; -- 複数件削除される可能性
対処法:事前確認の徹底
-- ステップ1:削除対象件数を確認
SELECT COUNT(*) FROM users WHERE name LIKE '%田中%';
-- ステップ2:具体的な内容を確認
SELECT id, name FROM users WHERE name LIKE '%田中%';
-- ステップ3:1件のみの場合はより具体的な条件を使用
DELETE FROM users WHERE id = 1 AND name = '田中太郎';
エラーを防ぐ最も重要なポイントは、DELETE文を実行する前の十分な確認と、段階的なアプローチです。
安全なDELETE運用のベストプラクティス

DELETE実行前のチェックリスト
必須確認項目
- WHERE句は適切か?
-- 削除対象を事前確認
SELECT COUNT(*) FROM users WHERE status = 'inactive'; SELECT id, name, email FROM users WHERE status = 'inactive';
- バックアップは取得済みか?
-- 重要なデータは事前バックアップ
CREATE TABLE users_backup_20250603 AS SELECT * FROM users WHERE status = 'inactive';
- 関連テーブルへの影響は確認したか?
-- 外部キー制約の確認
SELECT TABLE_NAME, COLUMN_NAME, REFERENCED_TABLE_NAME FROM information_schema.KEY_COLUMN_USAGE WHERE REFERENCED_TABLE_NAME = 'users';
段階的削除の実践
大量データの安全な削除手順
-- ステップ1:削除対象の特定
SELECT COUNT(*) FROM large_table WHERE created_at < '2024-01-01';
-- ステップ2:小さなバッチで削除開始
DELETE FROM large_table WHERE created_at < '2024-01-01' LIMIT 100;
-- ステップ3:結果確認
SELECT COUNT(*) FROM large_table WHERE created_at < '2024-01-01';
-- ステップ4:問題なければ続行
DELETE FROM large_table WHERE created_at < '2024-01-01' LIMIT 1000;
本番環境での安全対策
1. 読み取り専用ユーザーでの事前確認
-- 読み取り専用接続で確認作業
GRANT SELECT ON production_db.* TO 'readonly_user'@'%';
-- 本番データで削除対象を確認
SELECT * FROM users WHERE last_login < '2024-01-01' LIMIT 10;
2. メンテナンス時間での実行
-- 低負荷時間帯での実行
-- 深夜や早朝などユーザーが少ない時間を選択
3. 削除ログの記録
-- 削除実行前にログテーブルに記録
INSERT INTO deletion_log (table_name, condition_used, deleted_count, executed_by, executed_at)
VALUES ('users', 'status = inactive',
(SELECT COUNT(*) FROM users WHERE status = 'inactive'),
USER(), NOW());
復旧可能な削除の実装
ソフトデリート(論理削除)の導入
-- 物理削除の代わりに削除フラグを立てる
ALTER TABLE users ADD COLUMN deleted_at TIMESTAMP NULL;
ALTER TABLE users ADD COLUMN is_deleted BOOLEAN DEFAULT FALSE;
-- 削除の代わりに更新
UPDATE users SET is_deleted = TRUE, deleted_at = NOW() WHERE id = 1;
-- 表示時は削除されていないデータのみ
SELECT * FROM users WHERE is_deleted = FALSE;
-- 必要に応じて物理削除
DELETE FROM users WHERE is_deleted = TRUE AND deleted_at < DATE_SUB(NOW(), INTERVAL 30 DAY);
自動化と監視
定期的なデータクリーンアップの自動化
-- 古いログの自動削除(cron jobで実行)
DELIMITER //
CREATE PROCEDURE cleanup_old_logs()
BEGIN
DECLARE deleted_count INT;
-- 30日以上古いログを削除
DELETE FROM access_logs WHERE created_at < DATE_SUB(NOW(), INTERVAL 30 DAY);
SET deleted_count = ROW_COUNT();
-- 削除件数をログに記録
INSERT INTO cleanup_log (table_name, deleted_count, executed_at)
VALUES ('access_logs', deleted_count, NOW());
END //
DELIMITER ;
-- 毎日深夜2時に実行(crontab設定例)
-- 0 2 * * * mysql -u cleanup_user -p database_name -e "CALL cleanup_old_logs();"
エラー処理とアラート
削除処理のエラーハンドリング
DELIMITER //
CREATE PROCEDURE safe_bulk_delete(IN table_name VARCHAR(64), IN where_condition TEXT)
BEGIN
DECLARE error_count INT DEFAULT 0;
DECLARE deleted_count INT DEFAULT 0;
DECLARE done INT DEFAULT 0;
-- エラーハンドラー
DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
BEGIN
SET error_count = error_count + 1;
GET DIAGNOSTICS CONDITION 1
@error_code = MYSQL_ERRNO,
@error_message = MESSAGE_TEXT;
INSERT INTO deletion_errors (table_name, error_code, error_message, occurred_at)
VALUES (table_name, @error_code, @error_message, NOW());
END;
-- トランザクション開始
START TRANSACTION;
-- 削除実行
SET @sql = CONCAT('DELETE FROM ', table_name, ' WHERE ', where_condition, ' LIMIT 1000');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
SET deleted_count = ROW_COUNT();
-- エラーがなければコミット
IF error_count = 0 THEN
COMMIT;
INSERT INTO deletion_log (table_name, deleted_count, status, executed_at)
VALUES (table_name, deleted_count, 'SUCCESS', NOW());
ELSE
ROLLBACK;
INSERT INTO deletion_log (table_name, deleted_count, status, executed_at)
VALUES (table_name, 0, 'ERROR', NOW());
END IF;
END //
DELIMITER ;
削除権限の管理
最小権限の原則
-- 削除専用ユーザーの作成
CREATE USER 'delete_user'@'localhost' IDENTIFIED BY 'secure_password';
-- 特定のテーブルのみ削除権限を付与
GRANT DELETE ON app_db.temp_data TO 'delete_user'@'localhost';
GRANT DELETE ON app_db.old_logs TO 'delete_user'@'localhost';
-- SELECT権限も付与(事前確認のため)
GRANT SELECT ON app_db.* TO 'delete_user'@'localhost';
-- 権限の確認
SHOW GRANTS FOR 'delete_user'@'localhost';
時間制限付き権限
-- 特定の時間帯のみ削除を許可するトリガー
DELIMITER //
CREATE TRIGGER check_delete_time
BEFORE DELETE ON important_table
FOR EACH ROW
BEGIN
DECLARE current_hour INT;
SET current_hour = HOUR(NOW());
-- 深夜2時〜4時以外は削除を禁止
IF current_hour NOT BETWEEN 2 AND 4 THEN
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = 'Deletion is only allowed between 2:00-4:00 AM';
END IF;
END //
DELIMITER ;
パフォーマンス最適化
インデックスを活用した効率的な削除
-- 削除条件に使用するカラムにインデックス作成
CREATE INDEX idx_status_created ON users(status, created_at);
-- インデックスを活用した削除
DELETE FROM users WHERE status = 'inactive' AND created_at < '2024-01-01';
-- 実行計画の確認
EXPLAIN DELETE FROM users WHERE status = 'inactive' AND created_at < '2024-01-01';
パーティション分割テーブルでの効率的削除
-- 日付ベースのパーティション削除
ALTER TABLE logs DROP PARTITION p_2023_12; -- 2023年12月のデータを一括削除
まとめ
SQLのDELETE文は、データベース管理において非常に重要で強力な機能ですが、同時に慎重な取り扱いが必要な命令でもあります。
この記事で学んだ内容を整理してみましょう。
DELETE文の重要なポイント
- DELETE文は「行」を削除する命令で、テーブル構造は残る
- WHERE句は必須:条件指定なしだと全データが削除される
- 削除されたデータは基本的に復元できない
- 外部キー制約や権限エラーに注意が必要
安全な削除のための鉄則
- 事前確認は必須:SELECT文で削除対象を必ず確認
- バックアップを取る:重要なデータは削除前にバックアップ
- 段階的に実行:大量削除は小分けにして安全に
- トランザクションを活用:問題があれば取り消せるように
基本構文(復習)
-- 基本形
DELETE FROM テーブル名 WHERE 条件;
-- 安全な手順
-- ステップ1: 削除対象を確認
SELECT * FROM users WHERE status = 'inactive';
-- ステップ2: 削除実行
DELETE FROM users WHERE status = 'inactive';
-- ステップ3: 結果確認
SELECT COUNT(*) FROM users;
DELETEとTRUNCATEの使い分け
- DELETE:条件付き削除、ログ重視、安全性重視
- TRUNCATE:全削除、高速処理、ID リセット
よくあるエラーの対策
- 外部キー制約:子データから先に削除、またはCASCADE設定
- 権限不足:適切な権限の付与と最小権限の原則
- パフォーマンス:インデックスの活用とバッチ削除
コメント