データベースのテーブル削除は、開発・運用で頻繁に行う操作です。SQLのDROP TABLE文を使えば、不要になったテーブルを完全に削除できます。
しかし、DROP TABLEは取り消し不可能な操作のため、正しい知識がないと本番環境で重大な事故を起こしかねません。この記事では、基本構文からIF EXISTSによる安全な削除、外部キー制約の対処法、DROP TABLE・TRUNCATE TABLE・DELETEの違い、RDBMS別の構文比較まで、実務で必要な知識を網羅的に解説します。
この記事で学べること
- DROP TABLEの基本構文と実行例
- IF EXISTSでエラーを防ぐ安全な削除方法
- 複数テーブルの一括削除
- CASCADE CONSTRAINTSで外部キー制約ごと削除
- DROP TABLE・TRUNCATE TABLE・DELETEの使い分け
- INFORMATION_SCHEMAでテーブル存在を確認する方法
- MySQL・PostgreSQL・SQL Server・Oracle・SQLite別の構文比較
- 一時テーブルの削除方法
- よくあるエラーと対処法
- 実務での安全なテーブル削除パターン
DROP TABLEの基本構文
DROP TABLE文は、データベースからテーブルを完全に削除するSQL文です。テーブル定義(構造)とデータの両方が削除されます。
実行例
-- employeesテーブルを削除
DROP TABLE employees;
実行結果
Query OK, 0 rows affected (0.05 sec)
注意:DROP TABLEはDDL(Data Definition Language)に分類されます。実行すると自動的にCOMMITされるため、ROLLBACKで元に戻すことはできません。
DROP TABLEで削除されるもの
DROP TABLEを実行すると、以下のすべてが削除されます。
| 削除対象 |
説明 |
| テーブル定義 |
列名・データ型・制約などの構造情報 |
| 全データ |
テーブル内の全行 |
| インデックス |
テーブルに紐づくすべてのインデックス |
| トリガー |
テーブルに定義されたトリガー |
| 制約 |
PRIMARY KEY、UNIQUE、CHECK、DEFAULT等 |
| 権限 |
テーブルに付与されたGRANT(一部RDBMS) |
IF EXISTSでエラーを防ぐ
存在しないテーブルにDROP TABLEを実行するとエラーになります。IF EXISTSを付けると、テーブルが存在する場合のみ削除し、存在しない場合はエラーを出さずスキップします。
IF EXISTS 構文
-- テーブルが存在する場合のみ削除
DROP TABLE IF EXISTS employees;
IF EXISTSなしの場合(エラー発生)
存在しないテーブルを削除
-- employeesテーブルが存在しない場合
DROP TABLE employees;
エラー出力
ERROR 1051 (42S02): Unknown table 'database_name.employees'
IF EXISTSありの場合(エラーなし)
IF EXISTS で安全に削除
DROP TABLE IF EXISTS employees;
実行結果
Query OK, 0 rows affected, 1 warning (0.00 sec)
ポイント:マイグレーションスクリプトやバッチ処理では、IF EXISTSを付けるのが鉄則です。テーブルの有無に関わらずスクリプトが正常に実行されるため、環境差異による失敗を防げます。
複数テーブルの一括削除
DROP TABLE文では、カンマ区切りで複数のテーブルを同時に削除できます。
複数テーブルの一括削除
-- 3つのテーブルを同時に削除
DROP TABLE employees, departments, salaries;
IF EXISTS と組み合わせ
-- 存在するテーブルだけ削除
DROP TABLE IF EXISTS employees, departments, salaries;
注意:複数テーブルの一括削除はMySQL・PostgreSQL・SQLiteで対応しています。Oracle・SQL Serverでは1テーブルずつDROP TABLE文を実行する必要があります。
外部キーの依存関係を考慮した削除順序
外部キー制約がある場合、子テーブル → 親テーブルの順序で削除する必要があります。
正しい削除順序
-- orders → customers の外部キー関係がある場合
-- 子テーブル(参照する側)を先に削除
DROP TABLE IF EXISTS orders;
-- 親テーブル(参照される側)を後に削除
DROP TABLE IF EXISTS customers;
CASCADE CONSTRAINTS で外部キー制約ごと削除
外部キー制約がある親テーブルを削除しようとすると、通常はエラーになります。CASCADEオプションを使うと、関連する外部キー制約も一緒に削除できます。
外部キーが原因のエラー例
エラーが発生するケース
-- ordersテーブルがcustomersを外部キー参照している場合
DROP TABLE customers;
エラー出力(MySQL)
ERROR 3730 (HY000): Cannot drop table 'customers' referenced by a foreign key constraint 'orders_ibfk_1' on table 'orders'.
RDBMS別のCASCADE対処法
| RDBMS |
対処法 |
| PostgreSQL |
DROP TABLE テーブル名 CASCADE |
| Oracle |
DROP TABLE テーブル名 CASCADE CONSTRAINTS |
| MySQL |
SET FOREIGN_KEY_CHECKS = 0 で一時無効化 |
| SQL Server |
先に外部キー制約を個別に削除 |
| SQLite |
外部キーはデフォルト無効(PRAGMA foreign_keys) |
PostgreSQL: CASCADE
PostgreSQL – CASCADE
-- 外部キー制約も一緒に削除(子テーブルのデータは残る)
DROP TABLE customers CASCADE;
注意:PostgreSQLのCASCADEは外部キー制約を削除するだけで、子テーブル自体やそのデータは削除しません。あくまで「制約の連鎖削除」です。
Oracle: CASCADE CONSTRAINTS
Oracle – CASCADE CONSTRAINTS
-- 外部キー制約ごとテーブルを削除
DROP TABLE customers CASCADE CONSTRAINTS;
-- PURGE を付けるとごみ箱にも残さない
DROP TABLE customers CASCADE CONSTRAINTS PURGE;
MySQL: FOREIGN_KEY_CHECKS を無効化
MySQL – 外部キーチェック無効化
-- 外部キーチェックを一時的に無効化
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE IF EXISTS customers;
-- 外部キーチェックを再度有効化
SET FOREIGN_KEY_CHECKS = 1;
注意:FOREIGN_KEY_CHECKSを無効化した状態で親テーブルを削除すると、子テーブルの外部キー制約は宙ぶらりんになります。子テーブルの制約も手動で削除するか、子テーブルごと削除してください。
SQL Server: 外部キー制約を個別に削除
SQL Server – 制約を先に削除
-- 1. 外部キー制約を先に削除
ALTER TABLE orders
DROP CONSTRAINT FK_orders_customers;
-- 2. テーブルを削除
DROP TABLE customers;
DROP TABLE・TRUNCATE TABLE・DELETEの違い
テーブルのデータを消す方法は3つあります。それぞれの特徴と使い分けを理解しておきましょう。
| 比較項目 |
DROP TABLE |
TRUNCATE TABLE |
DELETE |
| テーブル定義 |
削除される |
残る |
残る |
| データ |
全削除 |
全削除 |
条件指定可 |
| WHERE句 |
不可 |
不可 |
可能 |
| ROLLBACK |
不可(DDL) |
不可(DDL) |
可能(DML) |
| AUTO_INCREMENT |
消える |
リセット |
継続 |
| トリガー発火 |
しない |
しない |
する |
| 速度 |
高速 |
高速 |
低速(大量データ時) |
| SQL分類 |
DDL |
DDL |
DML |
使い分けの目安
使い分けの例
-- テーブル自体が不要 → DROP TABLE
DROP TABLE IF EXISTS tmp_work_data;
-- テーブル構造は残して全データを削除 → TRUNCATE TABLE
TRUNCATE TABLE access_logs;
-- 特定の条件に合うデータだけ削除 → DELETE
DELETE FROM access_logs
WHERE created_at < '2024-01-01';
ポイント:開発環境でテーブルを作り直す場合はDROP TABLE → CREATE TABLEのセットが定番です。本番環境で全データを消すだけならTRUNCATE TABLEを使います。
テーブルの存在確認方法
DROP TABLEの前にテーブルの存在を確認したい場合、INFORMATION_SCHEMAやRDBMS固有のコマンドが使えます。
INFORMATION_SCHEMA(標準SQL)
MySQL / SQL Server / PostgreSQL
-- テーブルが存在するか確認
SELECT TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_SCHEMA = 'your_database'
AND TABLE_NAME = 'employees';
実行結果(テーブルが存在する場合)
+------------+
| TABLE_NAME |
+------------+
| employees |
+------------+
1 row in set (0.00 sec)
RDBMS別のテーブル一覧確認コマンド
| RDBMS |
テーブル一覧コマンド |
| MySQL |
SHOW TABLES; |
| PostgreSQL |
\dt または SELECT * FROM pg_tables; |
| SQL Server |
SELECT * FROM sys.tables; |
| Oracle |
SELECT * FROM user_tables; |
| SQLite |
.tables または SELECT * FROM sqlite_master; |
SQL Server: IF EXISTSの代替(OBJECT_ID)
SQL Server 2016より前のバージョンではIF EXISTS構文が使えないため、OBJECT_ID関数で存在確認します。
SQL Server – OBJECT_IDで存在確認
-- SQL Server 2016以降
DROP TABLE IF EXISTS employees;
-- SQL Server 2014以前
IF OBJECT_ID('dbo.employees', 'U') IS NOT NULL
DROP TABLE dbo.employees;
RDBMS別のDROP TABLE構文比較
DROP TABLEの構文はRDBMSによって微妙に異なります。ここでは主要5つのRDBMSの構文を比較します。
MySQL
MySQL
-- 基本
DROP TABLE employees;
-- IF EXISTS付き
DROP TABLE IF EXISTS employees;
-- 複数テーブル一括削除
DROP TABLE IF EXISTS employees, departments;
-- 一時テーブル削除
DROP TEMPORARY TABLE IF EXISTS tmp_work;
PostgreSQL
PostgreSQL
-- 基本
DROP TABLE employees;
-- IF EXISTS付き
DROP TABLE IF EXISTS employees;
-- CASCADE(外部キー制約も削除)
DROP TABLE IF EXISTS employees CASCADE;
-- RESTRICT(参照されていればエラー ※デフォルト)
DROP TABLE employees RESTRICT;
SQL Server
SQL Server
-- 基本
DROP TABLE employees;
-- IF EXISTS付き(SQL Server 2016以降)
DROP TABLE IF EXISTS employees;
-- スキーマ指定
DROP TABLE dbo.employees;
-- 旧バージョン対応
IF OBJECT_ID('dbo.employees', 'U') IS NOT NULL
DROP TABLE dbo.employees;
Oracle
Oracle
-- 基本(ごみ箱に入る)
DROP TABLE employees;
-- 完全削除(ごみ箱に入れない)
DROP TABLE employees PURGE;
-- 外部キー制約ごと削除
DROP TABLE employees CASCADE CONSTRAINTS;
-- 完全削除 + 外部キー制約ごと
DROP TABLE employees CASCADE CONSTRAINTS PURGE;
ポイント:OracleのDROP TABLEはIF EXISTS構文がありません(23c以降で対応予定)。存在確認が必要な場合はPL/SQLで対処します。
SQLite
SQLite
-- 基本
DROP TABLE employees;
-- IF EXISTS付き
DROP TABLE IF EXISTS employees;
RDBMS別対応状況まとめ
| 機能 |
MySQL |
PostgreSQL |
SQL Server |
Oracle |
SQLite |
| IF EXISTS |
○ |
○ |
○(2016〜) |
✕(23c〜) |
○ |
| 複数テーブル一括 |
○ |
○ |
✕ |
✕ |
○ |
| CASCADE |
✕ |
○ |
✕ |
○ |
✕ |
| PURGE |
✕ |
✕ |
✕ |
○ |
✕ |
| TEMPORARY指定 |
○ |
✕ |
✕ |
✕ |
✕ |
一時テーブルの削除
一時テーブル(TEMPORARY TABLE)はセッション終了時に自動削除されますが、明示的に削除することもできます。
MySQL: DROP TEMPORARY TABLE
MySQL – 一時テーブルの作成と削除
-- 一時テーブルを作成
CREATE TEMPORARY TABLE tmp_results (
id INT,
name VARCHAR(100)
);
-- 一時テーブルのみを削除(通常テーブルは影響なし)
DROP TEMPORARY TABLE IF EXISTS tmp_results;
ポイント:DROP TEMPORARY TABLEは一時テーブルだけを対象にするため、同名の通常テーブルを誤って削除する心配がありません。MySQLでは一時テーブルと通常テーブルが同名でも共存できます。
PostgreSQL・SQL Server
PostgreSQL / SQL Server – 一時テーブルの削除
-- PostgreSQL: 通常のDROP TABLEで削除
DROP TABLE IF EXISTS tmp_results;
-- SQL Server: #付きの一時テーブル
DROP TABLE IF EXISTS #tmp_results;
-- SQL Server: ##付きのグローバル一時テーブル
DROP TABLE IF EXISTS ##tmp_results;
| RDBMS |
一時テーブルの削除方法 |
自動削除タイミング |
| MySQL |
DROP TEMPORARY TABLE |
セッション終了時 |
| PostgreSQL |
DROP TABLE(通常と同じ) |
セッション終了時(ON COMMIT DROPも可) |
| SQL Server |
DROP TABLE #テーブル名 |
セッション終了時 / バッチ終了時 |
| Oracle |
DROP TABLE(通常と同じ) |
トランザクション/セッション終了時 |
| SQLite |
DROP TABLE(通常と同じ) |
接続終了時 |
DROP TABLE後のデータ復旧について
DROP TABLEで削除したテーブルとデータを元に戻せるかは、RDBMSと事前の対策によって異なります。
| RDBMS |
復旧方法 |
条件 |
| Oracle |
FLASHBACK TABLE(ごみ箱復元) |
PURGEしていない場合のみ |
| SQL Server |
トランザクションログからの復旧 |
完全復旧モデルの場合のみ |
| MySQL |
バックアップからの復元 |
事前にバックアップが必要 |
| PostgreSQL |
バックアップからの復元 |
事前にバックアップが必要 |
| SQLite |
ファイルバックアップからの復元 |
事前にファイルコピーが必要 |
Oracle: FLASHBACK TABLEで復旧
Oracle – ごみ箱から復元
-- ごみ箱の中身を確認
SELECT object_name, original_name, type
FROM user_recyclebin;
-- テーブルを復元
FLASHBACK TABLE employees TO BEFORE DROP;
-- 別名で復元
FLASHBACK TABLE employees TO BEFORE DROP RENAME TO employees_restored;
注意:DROP TABLE ... PURGEで削除した場合、ごみ箱に入らないためFLASHBACK TABLEでの復旧は不可能です。復旧の可能性を残すなら、PURGEは付けないようにしましょう。
MySQL: バックアップからの復旧
MySQL – mysqldumpからの復元
-- 事前にバックアップを取得しておく
mysqldump -u root -p my_database employees > employees_backup.sql
-- 復元する場合
mysql -u root -p my_database < employees_backup.sql
よくあるエラーと対処法
| エラー |
原因 |
対処法 |
Unknown table |
テーブルが存在しない |
IF EXISTSを使う |
foreign key constraint fails |
他のテーブルから参照されている |
CASCADE / FOREIGN_KEY_CHECKS=0 |
Access denied |
DROP権限がない |
GRANTで権限を付与 |
table is locked |
テーブルがロックされている |
UNLOCK TABLESまたはセッション終了を待つ |
syntax error |
予約語をテーブル名に使用 |
バッククォートで囲む |
table doesn't exist in engine |
メタデータと実体の不整合 |
.frmファイルを手動削除後に再作成 |
エラー1: テーブルが存在しない
エラーと対処法
-- エラーが出る
DROP TABLE non_existent_table;
-- ERROR 1051 (42S02): Unknown table 'db.non_existent_table'
-- 対処: IF EXISTSを付ける
DROP TABLE IF EXISTS non_existent_table;
エラー2: 外部キー制約によるエラー
MySQL - 外部キーエラーの対処
-- エラーが出る場合
DROP TABLE customers;
-- ERROR 3730: Cannot drop table referenced by foreign key
-- 対処1: 外部キーチェックを無効化
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE customers;
SET FOREIGN_KEY_CHECKS = 1;
-- 対処2: 子テーブルを先に削除
DROP TABLE orders; -- 子テーブルを先に
DROP TABLE customers; -- 親テーブルを後に
エラー3: 権限不足
MySQL - DROP権限の付与
-- 現在の権限を確認
SHOW GRANTS FOR 'username'@'localhost';
-- DROP権限を付与(管理者が実行)
GRANT DROP ON my_database.* TO 'username'@'localhost';
FLUSH PRIVILEGES;
エラー4: 予約語がテーブル名に使われている
予約語テーブルの削除
-- "order"は予約語なのでエラーになる
DROP TABLE order;
-- ERROR 1064: Syntax error
-- 対処: バッククォート(MySQL)やダブルクォート(標準SQL)で囲む
DROP TABLE `order`; -- MySQL
DROP TABLE "order"; -- PostgreSQL / Oracle
DROP TABLE [order]; -- SQL Server
実務での安全なテーブル削除パターン
本番環境でテーブルを削除する際は、以下の手順に沿って安全に作業を進めましょう。
ステップ1: 事前確認
事前確認 - テーブル構造とデータ件数
-- 1. テーブルの存在とデータ件数を確認
SELECT COUNT(*) AS row_count
FROM employees;
-- 2. 外部キー制約を確認(MySQL)
SELECT
TABLE_NAME,
CONSTRAINT_NAME,
REFERENCED_TABLE_NAME
FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE
WHERE REFERENCED_TABLE_NAME = 'employees';
-- 3. テーブル構造を確認
DESCRIBE employees;
ステップ2: バックアップ取得
バックアップ取得
-- MySQLの場合: mysqldumpでバックアップ
mysqldump -u root -p my_database employees > backup_employees_$(date +%Y%m%d).sql
-- SQL内でバックアップテーブルを作成する方法もある
CREATE TABLE employees_backup_20240301 AS
SELECT * FROM employees;
ステップ3: リネーム → 確認 → 削除
いきなりDROP TABLEするのではなく、リネームして問題がないか確認してから削除する方法が最も安全です。
安全な削除パターン(リネーム方式)
-- ステップ1: テーブルをリネーム(_dropme接尾辞を付ける)
ALTER TABLE employees
RENAME TO _employees_dropme_20240301;
-- ステップ2: アプリケーションに影響がないか1〜2週間確認
-- (エラーが出たらリネームを戻せばOK)
-- ステップ3: 問題なければ削除
DROP TABLE _employees_dropme_20240301;
実務での安全な削除チェックリスト
- 対象テーブルのデータ件数を確認した
- テーブルを参照している外部キー制約を確認した
- テーブルを使っているビュー・ストアドプロシージャがないか確認した
- アプリケーションコードで当該テーブルを参照している箇所がないか確認した
- バックアップを取得した
- 可能であればリネーム方式で一定期間運用確認した
- 作業はメンテナンス時間帯に実施する
マイグレーションスクリプトでのパターン
フレームワークのマイグレーション機能を使わず、手動でSQLスクリプトを実行する場合の安全なパターンです。
安全なマイグレーションスクリプト(MySQL)
-- ============================================
-- マイグレーション: 不要テーブルの削除
-- 実行日: 2024-03-01
-- 対象: old_logs, temp_data, deprecated_config
-- ============================================
-- バックアップテーブル作成
CREATE TABLE IF NOT EXISTS _bak_old_logs AS
SELECT * FROM old_logs;
-- 外部キーチェックを一時停止
SET FOREIGN_KEY_CHECKS = 0;
-- テーブル削除
DROP TABLE IF EXISTS old_logs;
DROP TABLE IF EXISTS temp_data;
DROP TABLE IF EXISTS deprecated_config;
-- 外部キーチェックを復元
SET FOREIGN_KEY_CHECKS = 1;
まとめ
DROP TABLEは、テーブルの定義・データ・インデックスをすべて削除するSQL文です。最後に要点を整理しておきましょう。
| ポイント |
内容 |
| 基本構文 |
DROP TABLE テーブル名; |
| 安全な削除 |
IF EXISTSを付けてエラーを防ぐ |
| 外部キー対処 |
CASCADE(PostgreSQL/Oracle)またはFOREIGN_KEY_CHECKS=0(MySQL) |
| TRUNCATE TABLE との違い |
DROP=テーブル自体を削除、TRUNCATE=データだけ削除 |
| データ復旧 |
Oracle以外は基本的にバックアップからのみ復旧可能 |
| 実務のコツ |
バックアップ取得 → リネーム → 確認 → 削除の手順 |
ポイント:DROP TABLEは取り消しができない強力なコマンドです。特に本番環境では、バックアップ取得 → リネーム → 動作確認 → 削除の手順を徹底し、事故を未然に防ぎましょう。