初心者向け!SQLのDELETE文の正しい使い方と注意点を解説

データベース・SQL

データベースを使っていると、「間違って登録したデータを削除したい」「古い情報を整理したい」という場面が必ずありますよね。

そんなときに使うのが「DELETE文」です。

でも、DELETE文はとても強力な命令なので、使い方を間違えると大切なデータをすべて失ってしまう危険があります。

この記事では、DELETE文を安全に使うための方法を、初心者の方でもわかるように丁寧に説明します。

この記事で学べること

  • DELETE文の基本的な使い方
  • 安全にデータを削除する方法
  • よくある間違いとその対策
  • DELETE文を使うときの重要な注意点

一緒に安全なデータ削除の方法を学んでいきましょう!

スポンサーリンク

DELETE文とは何か?

DELETE文の基本的な役割

DELETE文は、データベースのテーブルから「特定の行(レコード)」を削除するためのSQL命令です。

重要なポイント

  • 削除されるのは「行」であり、テーブル全体ではありません
  • 削除されたデータは基本的に復元できません
  • 条件を指定しないと、すべてのデータが削除されてしまいます

サンプルテーブルで理解しよう

以下のようなusersテーブルがあるとします:

usersテーブル

idnameagecitystatus
1田中太郎25Tokyoactive
2佐藤花子30Osakainactive
3鈴木一郎35Tokyoactive
4山田美咲28Kyotoinactive
5高橋健太32Tokyoactive

DELETE文の基本構文

DELETE FROM テーブル名 WHERE 条件;

各部分の説明

  • DELETE FROM:「〜から削除する」という意味
  • テーブル名:削除対象のテーブル名
  • WHERE 条件:どの行を削除するかの条件

具体的な削除例

特定のユーザーを削除

DELETE FROM users WHERE id = 2;

この命令を実行すると:

実行後のusersテーブル

idnameagecitystatus
1田中太郎25Tokyoactive
3鈴木一郎35Tokyoactive
4山田美咲28Kyotoinactive
5高橋健太32Tokyoactive

佐藤花子さん(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句が必要

全行削除してしまった場合の対処法

もし誤って全削除してしまった場合:

  1. すぐに作業を停止する
  2. バックアップから復元する
  3. バイナリログから復旧する(MySQL)
  4. データベース管理者に連絡する
-- バックアップからの復元例
SOURCE backup_file.sql;

-- 特定の時点まで復旧
mysqlbinlog --stop-datetime="2025-06-03 14:30:00" binlog.000001 | mysql

全行削除は取り返しのつかない事故につながります。必ず事前確認と安全対策を徹底しましょう。

DELETEとTRUNCATEの違いを理解しよう

TRUNCATEとは何か?

TRUNCATE文も、テーブルからデータを削除する命令ですが、DELETE文とは動作が大きく異なります。

TRUNCATE文の基本構文

TRUNCATE TABLE テーブル名;

主な違いの比較

項目DELETETRUNCATE
WHERE句使用可能(条件指定可)使用不可(全削除のみ)
削除速度比較的遅い非常に高速
ログ記録詳細に記録される最小限の記録
ロールバック可能一部データベースで不可
自動増分IDリセットされないリセットされる
外部キー制約チェックされるエラーになる場合あり
トリガー実行される実行されない

具体的な違いを見てみよう

サンプルテーブル:test_users

idnamecreated_at
1ユーザー12025-06-01 10:00:00
2ユーザー22025-06-02 11:00:00
3ユーザー32025-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実行前のチェックリスト

必須確認項目

  1. WHERE句は適切か?
    -- 削除対象を事前確認
    SELECT COUNT(*) FROM users WHERE status = 'inactive'; SELECT id, name, email FROM users WHERE status = 'inactive';
  2. バックアップは取得済みか?
    -- 重要なデータは事前バックアップ
    CREATE TABLE users_backup_20250603 AS SELECT * FROM users WHERE status = 'inactive';
  3. 関連テーブルへの影響は確認したか?
    -- 外部キー制約の確認
    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句は必須:条件指定なしだと全データが削除される
  • 削除されたデータは基本的に復元できない
  • 外部キー制約や権限エラーに注意が必要

安全な削除のための鉄則

  1. 事前確認は必須:SELECT文で削除対象を必ず確認
  2. バックアップを取る:重要なデータは削除前にバックアップ
  3. 段階的に実行:大量削除は小分けにして安全に
  4. トランザクションを活用:問題があれば取り消せるように

基本構文(復習)

-- 基本形
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設定
  • 権限不足:適切な権限の付与と最小権限の原則
  • パフォーマンス:インデックスの活用とバッチ削除

コメント

タイトルとURLをコピーしました