質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

Q&A

解決済

2回答

9457閲覧

配列にまとめたデータをDBに保存したい

smnsmn

総合スコア175

MySQL

MySQL(マイエスキューエル)は、TCX DataKonsultAB社などが開発するRDBMS(リレーショナルデータベースの管理システム)です。世界で最も人気の高いシステムで、オープンソースで開発されています。MySQLデータベースサーバは、高速性と信頼性があり、Linux、UNIX、Windowsなどの複数のプラットフォームで動作することができます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

0グッド

1クリップ

投稿2016/03/01 14:49

編集2016/03/01 14:50

hoge table
| id(int) | name(varchar) |

といったテーブルがあったとして、

100 鈴木
101 田中
102 山田

のようなデータを配列にまとめて一気にinsertしたいです。
イニシャライズというものを知りましたが、
配列にまとめる場合はどのような配列にすれば良いのでしょうか?

PHP

1$data = array('id' => array('101', '102', '103'), 2 ('name' => array('鈴木', '田中', '山田'); 3 4$data = array('id' => array('101' => array('name' => '鈴木'), 5 '102' => array('name' => '田中'), 6 '103' => array('name' => '山田') 7 ); 8```どれもイマイチ違うように思います・・・。 9 10クエリとしては下記で良いのでしょうか?(PHP上で実行します。) 11```PHP 12$query = "INSERT INTO hoge (id, name) " 13 ."VALUES (" 14 ."'".$data."'" 15 ")"; 16 17$result = mysql_query($query); 18

件数は大量ではありませんが、それでも多いのでforeachで回さずにできたらと思っています。
ご教授頂けると幸いです。

よろしくお願い致します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

データ数が多いのであればバルクインサート派です。
フレームワーク等によるかもしれませんが、
ウチの環境でクエリを複数投げると、SQLのコスト以前に、PHPからMySQLに接続するコストがでかいので。

ということでバルクインサートバージョンを。

データ部分($data)はdupont_kedamaさんと同じ形で、あとはクエリ文の生成を↓のような要領でやります。

php

1// クエリ生成 2$query = "INSERT INTO `hoge` (`id`, `name`) VALUES "; 3foreach ($data AS $val) 4{ 5 $query_values[] = "(" . $val['id'] . ",'" . $val['name'] . "')"; 6} 7$query = $query . implode(",", $query_values);

わたしは普段プレースホルダでやってるので、本当は↓のような書き方をしています。
(値が入るところが「?」になっています)

php

1// クエリ生成 2$query = "INSERT INTO `hoge` (`id`, `name`) "; 3$query .= "VALUES " . implode("," ,array_fill(0, count($data), "(?, ?)")); 4 5// この場合は、クエリ投げる用の配列を別途整形する必要があります 6$value = array(101, "鈴木", 102, "田中"); // …という形になるはず

投稿2016/03/02 01:29

takushi168

総合スコア228

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

smnsmn

2016/03/02 07:04

ご回答ありがとうございます。 なるほど、配列に入れた値をinsert文に全部記述してしまうのですね。 >// この場合は、クエリ投げる用の配列を別途整形する必要があります  $value = array(101, "鈴木", 102, "田中"); // …という形になるはず これはどういう意味でしょうか?;; $dataとは別に$valueが必要ということでしょうか? $queryの中で$valueは出てきていないと思いまうすが、何に必要なのでしょうか? よろしければご教授いただけませんでしょうか。mm
smnsmn

2016/03/02 08:36

バルクインサートもとてもわかりやすかったです。ありがとうございます。 色々な方法を覚えていきたいと思います!m(__)m
guest

0

ベストアンサー

PHP

1$data = array( 2 array( 3 'id' => 101, 4 'name' => '鈴木', 5 ), 6 array( 7 'id' => 102, 8 'name' => '田中', 9 ), 10); 11 12$dbh = new PDO('mysql:host=xxxxx;dbname=xxxxx;charset=utf8','xxxxx','xxxxx'); 13$stmt = $dbh->prepare("INSERT INTO hoge (id, name) VALUES (:id, :name)"); 14$stmt->bindParam(':id', $id, PDO::PARAM_INT); 15$stmt->bindParam(':name', $name, PDO::PARAM_STR); 16 17$dbh->beginTransaction(); 18foreach($data as $datum) { 19 $id = $datum['id']; 20 $name = $datum['name']; 21 $stmt->execute(); 22} 23$dbh->commit();

こんな感じでどうでしょう。

クエリ部分はプリペアドステートメントで構成し、全体をトランザクション(beginTransactionとcommit)で囲んでおけばforeachでまわすのでも問題ないと思いますよ。
ひとつのINSERT文で複数の行を挿入するバルクインサートという方法もありますが、上↑の方法の方が処理が簡単で、パフォーマンスもそう変わらないと思います。

解説追記

(バインドとは・・・ここはどういった処理なのでしょうか?;;)

:idの名前がついている箇所に変数$idを紐づける操作をしています。
PHP PDOStatement::bindParam

(トランザクションを貼ると、途中でエラーが出たら、ロールバックといって処理開始時の時点までデータを戻すことができる(?))

間違ってはいないです。このケースの場合はエラー対策はもちろんですが主にDBへのI/Oを減らすために囲んでいます。

$stmt->execute(); //プリペアドステートメント開始(?)

プリペアドステートメントは$stmt = $dbh->prepare("INSERT INTO hoge (id, name) VALUES (:id, :name)");で作っています。
execute()はSQLの実行をしている箇所です。
PHP PDOStatement::execute

上記のececute()に引数は指定しないのでしょうか?

この書き方の場合は引数は不要です。

$datumをforeachで作っていますがその後使用しないのでしょうか?;;;

しません。使えないわけではないですが、多くの場合foreachの外では使い道はありません。

bindValueパターン

PHP

1$dbh = new PDO('mysql:host=xxxxx;dbname=xxxxx;charset=utf8','xxxxx','xxxxx'); 2$stmt = $dbh->prepare("INSERT INTO hoge (id, name) VALUES (:id, :name)"); 3 4$dbh->beginTransaction(); 5foreach($data as $datum) { 6 $stmt->bindValue(':id', $datum['id'], PDO::PARAM_INT); 7 $stmt->bindValue(':name', $datum['name'], PDO::PARAM_STR); 8 $stmt->execute(); 9} 10$dbh->commit();

bindParam()と違って値自体をバインドするので、$id、$namaの変数は使いません。

投稿2016/03/01 15:32

編集2016/03/02 08:59
dupont_kedama

総合スコア925

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dupont_kedama

2016/03/02 01:54

バルクインサートの場合、クエリが極端に長くなりすぎるとmax_allowed_packetを超えてしまうことがあるのでご注意ください。
smnsmn

2016/03/02 06:59

ご回答ありがとうございます。 初めて用語ばかりで少し戸惑っておりますのでよろしければご解説いただけないでしょうか? //DBに接続・クエリの記述 $dbh = new PDO('mysql:host=xxxxx;dbname=xxxxx;charset=utf8','xxxxx','xxxxx'); $stmt = $dbh->prepare("INSERT INTO hoge (id, name) VALUES (:id, :name)"); //指定された変数名にパラメータをバインドする //(バインドとは・・・ここはどういった処理なのでしょうか?;;) $stmt->bindParam(':id', $id, PDO::PARAM_INT); $stmt->bindParam(':name', $name, PDO::PARAM_STR); //トランザクション開始 (トランザクションを貼ると、途中でエラーが出たら、ロールバックといって処理開始時の時点までデータを戻すことができる(?)) $dbh->beginTransaction(); foreach($data as $datum) { $id = $datum['id']; $name = $datum['name']; $stmt->execute(); //プリペアドステートメント開始(?) } $dbh->commit(); 上記のececute()に引数は指定しないのでしょうか? $datumをforeachで作っていますがその後使用しないのでしょうか?;;; 質問ばかりで申し訳ありません。 何卒よろしくお願い致します。 ※ちなみに今回扱うレコード数は300件くらいを想定しています。(2〜3カラム)
smnsmn

2016/03/02 08:34

ありがとうございます。 徐々にですが理解できました。 $datumをforeachで作っていますがその後使用しないのでしょうか?;;; >しません。使えないわけではないですが、多くの場合foreachの外では使い道はありません。 少し勘違いしておりました。 foreach($data as $datum)内で$dataを$datumに入れ、 $id にid、$nameにnameを代入し、 バインドで:idの名前がついている箇所に変数$idを紐づけているので 最後に$stmt->execute();でSQL実行・・・ といった感じでしょうか。;;; 先にバインドしているので、その後で$idなどに値を代入するだけで良いのですね・・・・。 とても勉強になりました! ありがとうございますm(__)m
dupont_kedama

2016/03/02 08:53

ご理解いただいていると思いますが、補足です。 回答の書き方では、$dataには「挿入したい行データの配列」が配列で保持されています。多重配列です。 foreachでは外側の配列を展開しているので、$datumには「挿入したい行データの配列」が1つずつ入ります。 bindParamの挙動は少し理解するのに時間がかかったかもしれません。 bindValueの方が直感的かもしれないのであとで回答に追記しておきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問