PDOによるMySQLのINSERT文を使って、データベースにデータを登録します。
mysql_query()
がPHP5.5で非推奨となり7.0で削除されたため、現在のPHPによるデータベース接続はPDOが主流となっています。
今回は、INSERT文とこのPDOを使ったMySQLのデータ登録方法ですが、パフォーマンスやセキュリティも考慮し、プリペアドステートメントを使っています。
複数のデータを一括で登録する方法もご紹介します。
INSERT文の基本
本記事のテーブル構文
INSERT文を使ったデータ挿入を見て行く前に、まず本記事で使用するデータベーステーブルを見てみましょう。
テーブル名:citys
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でINSERT文を使ってMySQLにデータを挿入し、完了メッセージをブラウザに出力するまでをひと通り見てみましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// INSERT文を変数に格納 $sql = "INSERT INTO citys (name, population, created) VALUES (:name, :population, now())"; // 挿入する値は空のまま、SQL実行の準備をする $stmt = $dbh->prepare($sql); // 挿入する値を配列に格納する $params = array(':name' => '綾瀬', ':population' => '84000'); // 挿入する値が入った変数をexecuteにセットしてSQLを実行 $stmt->execute($params); // 登録完了のメッセージ echo '登録完了しました'; |
以下のデータが挿入される
+–+——+———+——————————+
| 6 | 綾瀬 | 84000 | 2016-04-05 15:00:00 |
+–+——+———+——————————+
上記のように、現在日時を含めデータベースに挿入されます。
※now()
は現在日時を取得するSQL関数です。
※当サンプルはデータベース接続後からのコードを記載しています。データベースの接続を知りたい方は下記ページをご覧ください。
※当サンプルの変数$dbhは、上記ページでもご紹介しているデータベースの接続に関するプログラムが格納されています。
説明
上記サンプルの概要は以下のようになっています。
- データを挿入するINSERT文を変数に格納する(値を格納する
VALUES
の部分は後から値を入れる)
$sql = “INSERT INTO citys (name, population, created) VALUES (:name, :population, now())”;
:name
や:population
はプレースホルダと呼ばれ、値を入れるための単なる空箱。SQL実行時に値を入れるため、このSQL文は何度も使い回しができ、パフォーマンス的にも優れる。 - 値が空のままのSQL文を
prepare()
にセットし、SQL実行のための準備を行う
$stmt = $dbh->prepare($sql); - 実際に挿入する値を配列に格納
$params = array(‘:name’ => ‘綾瀬’, ‘:population’ => ‘84000’); - そして
execute()
に値が入った配列をセットしてSQLを実行し、データベースにデータを挿入する
$stmt->execute($params);
大まかな流れは以下のようになります。
SQLの実行準備(prepareにテンプレートとなるSQL文を準備しておく) => SQLの実行(executeに値をセットして実行する)
複数のデータを挿入するなどのSQLを複数回実行する場面でも、SQLの準備は最初の1回のみで、2回目以降は値を変えて実行を繰り返すだけでいいので、パフォーマンス的にもいいですね。
そして、上記サンプルのようにユーザーから値が送信されるような場面では、SQLインジェクションによる攻撃の標的となるため、prepare()
とexecute()
を使ったプリペアドステートメントという方法でSQLを実行する方法が一般的です。
値をセットする際に自動的にエスケープ処理してくれるため、セキュリティ的にもプリペアドステートメントを使うようにしたいですね。
INSERT文の構文
INSERT INTO テーブル名 ( フィールド1 [ , フィールド2 , フィールド3 … ]) VALUES ( フィールド1の値 [ , フィールド2の値 , フィールド3の値 …] )
([ ]はフィールドが複数ある場合)
テーブル名を指定した後の最初のカッコ内にフィールド名を入れ、VALUES
を挟んで、2つ目のカッコ内には値を指定します。
複数のフィールドに値を挿入したい場合は、最初のカッコ内の順番どおりに2つ目のカッコ内に値を指定していきます。
複数のデータをINSERT
先ほどのサンプルでは1つのデータを挿入していましたが、以下のサンプルでは複数のデータを一気に挿入する方法をご紹介します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// INSERT文を変数に格納 $sql = "INSERT INTO citys (name, population, created) VALUES (:name, :population, now())"; // 挿入する値は空のまま、SQL実行の準備をする $stmt = $dbh->prepare($sql); // 挿入する値を連想配列に格納する $citys = array('座間'=>129400, '綾瀬'=>84000); // foreachで挿入する値を1つずつループ処理 foreach ($citys as $key => $val) { // 連想配列のキーを :name に、値を :population にセットし、executeでSQLを実行 $stmt->execute(array(':name' => $key, ':population' => $val)); } |
以下のデータが挿入される
+–+——+———-+——————————+
| 6 | 座間 | 129400 | 2016-04-05 15:00:00 |
+–+——+———-+——————————+
| 7 | 綾瀬 | 84000 | 2016-04-05 15:00:00 |
+–+——+———-+——————————+
上記のように、一気に2つのデータが格納されました。
:◯◯ のようなプレースホルダを活用することで、ループ処理で一気に複数のデータを挿入することもできます。
下記のソースでエラーは出ないのですが、データベースには反映されません。
何が問題かご教授いただけないでしょうか?
ちなみに、サーバーはお名前.comの共用サーバーです。
getMessage();
exit;
}
$sql = “INSERT INTO ipcheck (ip, count) VALUES (:ip, :count)”;
$stmt = $dbh->prepare($sql);
$params = array(‘:ip’ => ‘222222’, ‘:count’ => ‘3’);
$stmt->execute($params);
?>
$sql = “INSERT INTO ipcheck (ip, count) VALUES (:ip, :count)”; より上の部分がおかしいようです。
以下ページのDBに接続するコードは記述されてますでしょうか?
http://www.flatflag.nir87.com/pdo_construct-912
こちらがないとDBに接続しないためご確認をお願いいたします。
すごくわかりやすかったです。ありがとうございました!
ありがとうございます。今後とも分かりやすい記事作成に努めてまいります。