PDOによるMySQLのDELETE文を使って、データベースのデータを削除します。
mysql_query()がPHP5.5で非推奨となり7.0で削除されたため、現在のPHPによるデータベース接続はPDOが主流となっています。
今回は、DELETE文とこのPDOを使ったMySQLのデータ削除方法ですが、パフォーマンスやセキュリティも考慮し、プリペアドステートメントを使っています。
複数のデータを一括で削除する方法もご紹介します。
※データを削除する際、誤って必要なデータが削除されないよう充分注意してください。
DELETE文の基本
本記事のテーブル構文
DELETE文を使ったデータ削除を見て行く前に、まず本記事で使用するデータベーステーブルを見てみましょう。
テーブル名:cities
id | name | population | created |
---|---|---|---|
1 | 相模原 | 717500 | 2016-04-05 13:41:00 |
2 | 大和 | 230700 | 2016-04-05 13:41:00 |
3 | 海老名 | 127700 | 2016-04-05 13:41:00 |
4 | 厚木 | 224400 | 2016-04-05 13:41:00 |
5 | 藤沢 | 409700 | 2016-04-05 13:41:00 |
神奈川県の都市名と人口がまとめられたテーブルになっています。
一番左のIDのフィールドは、オートインクリメントによりIDが自動で振られます。
基本的なコード
それでは、PDOでDELETE文を使ってデータを削除し、完了メッセージをブラウザに出力するまでをひと通り見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// DELETE文を変数に格納 $sql = "DELETE FROM cities WHERE id = :id"; // 削除するレコードのIDは空のまま、SQL実行の準備をする $stmt = $dbh->prepare($sql); // 削除するレコードのIDを配列に格納する $params = array(':id'=>5); // 削除するレコードのIDが入った変数をexecuteにセットしてSQLを実行 $stmt->execute($params); // 削除完了のメッセージ echo '削除完了しました'; |
下記レコードが削除されます。
+–+——+———–+——————————+
| 5 | 藤沢 | 409700 | 2016-04-05 15:00:00 |
+–+——+———–+——————————+
下記のように、フィールド id の値が 5 の「藤沢」のレコードが削除されました。
+–+——–+———–+——————————+
| 1 | 相模原 | 717500 | 2016-04-05 15:00:00 |
+–+——–+———–+——————————+
| 2 | 大和 | 230700 | 2016-04-05 15:00:00 |
+–+——–+———–+——————————+
| 3 | 海老名 | 127700 | 2016-04-05 15:00:00 |
+–+——–+———–+——————————+
| 4 | 厚木 | 224400 | 2016-04-05 15:00:00 |
+–+——–+———–+——————————+
「レコード」とは?
レコードはデータテーブルの「行」のことで、1件分のデータのことです。
この例では、ID、都市名(name)、人口(population)の1行がレコードの1件分となります。
ちなみに、フィールドは「列」のことで、「カラム」とも呼ばれます。
※当サンプルはデータベース接続後からのコードを記載しています。データベースの接続を知りたい方は下記ページをご覧ください。
※当サンプルの変数$dbhは、上記ページでもご紹介しているデータベースの接続に関するプログラムが格納されています。
説明
上記サンプルの概要は以下のようになっています。
- データを削除するDELETE文を変数に格納する(削除するレコードのIDを入れる
WHERE
の部分は後から値を入れる)
$sql = “DELETE FROM cities WHERE id = :id”; - :id は
プレースホルダ
と呼ばれ、値を入れるための単なる空箱。SQL実行時に値を入れるため、このSQL文は何度も使い回しができ、パフォーマンス的にも優れる。 - 値が空のままのSQL文を
prepare()
にセットし、SQL実行のための準備を行う
$stmt = $dbh->prepare($sql); - 実際に削除するレコードのIDを配列に格納
$params = array(‘:id’=>5); - そして
execute()
に値が入った配列をセットしてSQLを実行し、データベースのデータを削除する
$stmt->execute($params);
大まかな流れは以下のようになります。
SQLの実行準備(prepareにテンプレートとなるSQL文を準備しておく) => SQLの実行(executeに値をセットして実行する)
複数のデータを削除するなどのSQLを複数回実行する場面でも、SQLの準備は最初の1回のみで、2回目以降は値を変えて実行を繰り返すだけでいいので、パフォーマンス的にもいいですね。
そして、上記サンプルのようにユーザーから値が送信されるような場面では、SQLインジェクションによる攻撃の標的となるため、prepare()
と execute()
を使った プリペアドステートメント
という方法でSQLを実行する方法が一般的です。
値をセットする際に自動的にエスケープ処理してくれるため、セキュリティ的にもプリペアドステートメントを使うようにしたいですね。
DELETE文の構文
DELETE FROM テーブル名 WHERE フィールド名 = 値
DELETE FROM
の後にまずテーブル名を指定し、WHERE
で削除するレコードのフィールド名と値を指定します。
複数のデータをDELETE
先ほどのサンプルでは1件のレコードを削除していましたが、以下のサンプルでは複数のレコードを一気に削除する方法をご紹介します。
複数のレコードを削除
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
// DELETE文を変数に格納 $sql = "DELETE FROM cities WHERE id = :id"; // 削除するレコードのIDは空のまま、SQL実行の準備をする $stmt = $dbh->prepare($sql); // 削除するレコードが複数の場合はカンマ区切りで追加する $params = array(4, 5); // foreachで削除するレコードを1件ずつループ処理 foreach ($params as $value) { // 配列の値を :id にセットし、executeでSQLを実行 $stmt->execute(array(':id' => $value)); } // 削除完了のメッセージ echo '削除完了しました'; |
下記レコードが削除されます。
+–+——+———–+—————————–+
| 4 | 厚木 | 224400 | 2016-04-05 15:00:00 |
+–+——+———–+—————————–+
| 5 | 藤沢 | 409700 | 2016-04-05 15:00:00 |
+–+——+———–+—————————–+
下記のように、フィールド id の値が 4と5 の「厚木」と「藤沢」のレコードが削除されました。
+–+——–+———–+——————————+
| 1 | 相模原 | 717500 | 2016-04-05 15:00:00 |
+–+——–+———–+——————————+
| 2 | 大和 | 230700 | 2016-04-05 15:00:00 |
+–+——–+———–+——————————+
| 3 | 海老名 | 127700 | 2016-04-05 15:00:00 |
+–+——–+———–+——————————+
上記のように、一気に2件のレコードが削除されました。
:◯◯ のようなプレースホルダを活用することで、ループ処理で一気に複数レコードを削除することもできます。