目次
SQLのDELETEでテーブルの行を削除
SQLのDELETEは、データベーステーブルに存在する行(レコード)削除するSQL命令です。
DELETEをテーブルからすべての行を消したり、特定の条件に一致したレコードをデータベーステーブルから削除することができます。
DELETE構文
DELETE文の構文は次の通りです。
WHERE以降の条件を省略すると、テーブルのレコードをすべて削除することができます。
DELETE FROM <テーブル名> WHERE <削除条件>
DELETE文の使い方
では、いくつかの例をみながらDELETE文の使い方を見ていきましょう。
テーブルからすべての行を削除する
テーブルのすべての行(レコード)削除するときは、条件なしのDELETEを実行します。
DELETE FROM users;
条件を指定して行を削除する
特定の条件に一致する行(レコード)だけを削除する場合は、WHERE句で削除する条件を指定します。
DELETE FROM users WHERE age < 20;
複数のデータを操作する場合はトランザクションを使用
DELETE、UPDATE、INSERTなど、複数のSQL文でデータベーステーブルの行を操作するとき、データ一貫性を保つためトランザクションを使用します。
例えば次のような、「商品マスタ」と「商品詳細」テーブルの2つが存在し、商品の廃止に伴い、2つのテーブルから該当の商品のレコードを削除するケースで考えてみましょう。
■ 商品マスタ
商品コード | 商品名
----------------------------------
00001 | マウス
00002 | キーボード
00003 | プリンタ
■ 商品詳細
商品コード | 型番 ❘金額
----------------------------------
00001 | A001 | 1,000
00001 | A002 | 2,000
00002 | B01 | 3,000
00003 | C01 | 10,000
もし、トランザクションを使用していないと、途中のSQLで実行エラーになっても、その途中まで正常に実行されたSQLの変更は保存(コミット)されます。
そのため、次のように商品マスタ、商品詳細の順に削除するSQLを実行し、2つめの商品詳細を削除するSQLでエラーが発生した場合、商品マスタの削除は保存(コミット)されているため、商品詳細テーブルに、商品マスタに存在しないレコードが生まれ、データの不整合が発生します。
mysql> DELETE FROM 商品マスタ WHERE 商品コード = '00002'; -- 正常に1レコードを削除
mysql> DELETE FROM 商品詳細 WHERE 商品コード = '00002'; -- ★エラーが発生
【SQL実行後のテーブル】
■ 商品マスタ
商品コード | 商品名
----------------------------------
00001 | マウス
00003 | プリンタ
■ 商品詳細
商品コード | 型番 ❘金額
----------------------------------
00001 | A001 | 1,000
00001 | A002 | 2,000
00002 | B01 | 3,000 ← SQLの失敗により商品マスタに存在しないレコードが発生する
00003 | C01 | 10,000
トランザクションを使用すれば、上記のようなデータ不整合は発生しません。
Oracle、SQL Server、MySQLなど、ほとんどのRDB(リレーショナルデータベース)には、トランザクション機能があり、DELETE文などのデータを変更するSQLを実行する前に、トランザクションを開始します。
トランザクション内で実行されたSQLは、コミット命令を実行するまで、データの保存が保留され、コミット命令実行時にそれまでの変更がすべて保存され、逆にSQLエラーなどが発生し、トランザクション内で行われた変更をすべて元に戻したい時は、ロールバック命令を実行します。
トランザクションを使ったSQLコマンドの例
実際にMySQLを使って、トランザクション機能を試してみましょう。
商品マスタと商品詳細のDELETE文を実行する前に、トランザクションを開始し、最後にトランザクションをロールバックして、本当にデータが元に戻るのか確認します。
MySQLでは、トランザクションはBEGIN命令で開始します。
mysql> BEGIN; --トランザクションを開始
mysql> DELETE FROM 商品マスタ WHERE 商品コード = '00002'; -- 正常に1レコードを削除
mysql> DELETE FROM 商品詳細 WHERE 商品コード = '00002'; -- ★エラーが発生
mysql> ROLLBACK; --問題が発生したため、すべての変更を元に戻す(ロールバック)
上のSQL実行の、テーブルの内容は次の通りです。ロールバックしたことに処理、DELETE文で削除された商品マスタのレコードが元に戻っていることが分かります。
■ 商品マスタ
商品コード | 商品名
----------------------------------
00001 | マウス
00002 | キーボード -- ← ロールバックすることで、DELETE文の変更が元に戻る
00003 | プリンタ
■ 商品詳細
商品コード | 型番 ❘金額
----------------------------------
00001 | A001 | 1,000
00001 | A002 | 2,000
00002 | B01 | 3,000
00003 | C01 | 10,000
このように、複数のテーブルや、同じテーブルでも複数回のSQLによって、データを変更する場合は、トランザクションを使用して、SQLの途中で問題が発生した時にデータが元に戻せるようにしておきましょう。
全レコード消すならTRUNCATEが高速
テーブルからすべての行(レコード)を削除する場合は、DELETE文よりもTRUNCATE文を使用する方が、高速に処理ができます。
DELETE文は、テーブルのデータを1件ずつ削除するのに対し、TRUNCATEは一旦テーブルを削除してから、もう一度同じテーブルを作成するため、高速に処理が行えます。
例えば、数億レコードもあるテーブルを、DELETE文を使って行を削除する場合、SQLの実行に数分~数時間かかることもあるのに対し、TRUNCATEはデータ数にあまり関わらず、数秒程度でテーブルの行をすべて削除することができます。
TRUNCATEの使い方
TRUNCATE文の使い方は以下の通りです。
TRUNCATE TABLE <テーブル名>
まとめ
SQLのDELETEの使い方や、トランザクションを使用したSQLの実行などについて解説してきました。DELETE文は、SQLの基本の1つでもあるため、しっかり覚えておきましょう。
TRUNCATE文は高速ですが、使用にあたっていくつか注意点があります。
まず1つめが、自動的に連番を付与するAUTO_INCREMENTが設定されているカラムが存在するテーブルを、TRUNCATEで行をすべて削除すると、AUTO_INCREMENTが1にリセットされ、行の登録時に再び1から連番がセットされます。
2つめの注意点は、TRUNCATEはロールバックバックできません。またTRUNCATEの実行によって、自動的にコミットが行われるため、それまでDELETE文などで変更された行の内容が自動的に保存されます。