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

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

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

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

PHP

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

Q&A

解決済

3回答

2039閲覧

PHP配列、MYSQLのINSRTについて

kirin311

総合スコア53

MySQL

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

PHP

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

0グッド

0クリップ

投稿2018/06/04 02:09

編集2018/06/04 07:55

前提・実現したいこと

配列のデータを、MYSQLのデータベースへISERTしたい。

発生している問題・エラーメッセージ

配列のINSERTがうまくいかず、どうしても失敗した場合Falseが返ってきて、解決できないのでアドバイスを頂ければと思います。
当方としては、どこか原因かわからないのでぜひお願いします。
※DB接続自体は問題ないです。

テーブル
|no1(int)|no2(int)|first_name(varchar)|last_name(varchar)|email(varchar)
|:--|:--|--|
|1|1|tokumei|kibou| mailaddress

該当のソースコード

$dataの内容 ※Stringの中身は、見せられないので空白にしております。 array (size=3) 0 => array (size=5) 'no1' => string '' (length=0) 'no2' => string '' (length=0) 'first_name' => string '' (length=0) 'last_name' => string '' (length=0) 'email' => string '' (length=0) 1 => array (size=5) 'no1' => string '' (length=0) 'no2' => string '' (length=0) 'first_name' => string '' (length=0) 'last_name' => string '' (length=0) 'email' => string '' (length=0) 2 => array (size=5) 'no1' => string '' (length=0) 'no2' => string '' (length=0) 'first_name' => string '' (length=0) 'last_name' => string '' (length=0) 'email' => string '' (length=0) . . .

php

1public function Insert($data) { 2    foreach ($data as $key => $val) {//プレースホルダーの生成 3      foreach ($val as $key2 => $val2) { 4         $values[] = ':' . $key2; 5      } 6    } 7 8 /* 9 こちらは正常、ただし一つだけしか入らない。 10 $sql = "INSERT INTO $this->table_name VALUES 11 (1, 1,'名前', 'なし' , 'mailaddress@ddd.jp')"; 12 */ 13 $sql = sprintf("INSERT INTO %s VALUES (%s)",$this->table_name,implode(',', $values)); 14 15 16 $stmt = $this->db->prepare($sql);//挿入する値は空のまま、SQL実行の準備 17 18 foreach ($data as $key => $val) { 19 foreach ($val as $key2 => $val2) { 20 $stmt->bindValue(':' . $key2, $val2);//成功した場合True、失敗した場合Falseが返ってくる 21 } 22 } 23 24 $result = $stmt->execute();//データベースに書き込み実行する 25 26 //簡易チェック 27 if($result){ 28 var_dump('成功'); 29 }else{ 30 var_dump('失敗'); 31 } 32 33 return $result; 34}

試したこと

var_dump($data)や、簡易チェックを用いたり、実際に動作してやってみたのですが、データベースのほうに挿入されません・・

###修正後コード
以下の通りコードの変更いたしました。
こちらでも、書き込み失敗します。

SQL構文
'INSERT INTO テーブル名 VALUES
(:no10,:no20,:first_name0,:last_name0,:email0),
(:no11,:no21,:first_name1,:last_name1,:email1),
(:no12,:no22,:first_name2,:last_name2,:email2),
(:no13,:no23,:first_name3,:last_name3,:email3)'

PHP

1try { 2 $values = []; 3 foreach ($data as $rownum => $row) { 4 $rowvalues = []; 5 foreach ($row as $column => $value) { 6 $rowvalues[] = ':' . $column . $rownum; 7 } 8 $values[] = '(' . implode(',', $rowvalues) . ')'; 9 } 10 $sql = sprintf("INSERT INTO %s VALUES %s", $this->table_name, implode(',', $values)); 11 $stmt = $this->db->prepare($sql); 12 if (!$stmt) { 13 echo "\nPDO::errorInfo():\n"; 14 var_dump($stmt->errorInfo()); 15 } 16 foreach ($data as $rownum => $row) { 17 foreach ($row as $column => $value) { 18 $stmt->bindValue(':' . $column . $row_num, $value); 19 } 20 } 21 $result = $stmt->execute(); 22 if ($result) { 23 var_dump('成功'); 24 } else { 25 var_dump('失敗'); 26 } 27} 28catch(PDOException $e) { 29 echo "データベースエラー(PDOエラー)"; 30 var_dump($e->getMessage()); 31} 32return $result; 33 34} 35

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

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

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

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

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

m.ts10806

2018/06/04 02:21 編集

インデントをきちんとつけていただけますか? また ```php  というのがコード内に出てしまっています``` ```phpのようになってしまっているものと思われますので```php だけにしてください。
kirin311

2018/06/04 02:22

すみません、修正いたします。
m.ts10806

2018/06/04 02:35 編集

インデント全角スペースではエラーになります。PHPの整形サービス( http://flatsystems.net/php_beautifier.php )かフォーマッターがついているエディタを利用してください。
kirin311

2018/06/04 02:40

整形サービス利用させていただきました、ありがとうございます
guest

回答3

0

複数一気にINSERTしたい場合、MySQLではINSERT INTO table_name VALUES (...), (...), (...)のように書かないといけません。カッコ自体が複数必要になります。また、当然ですがプレースホルダーはそれぞれ別のキーになるようにする、あるいは?を使って順番だけで処理できるようにしておかないと、バラバラに代入できなくなります。

ということで、対策法としては2つ考えられまして、

  • 「SQL文生成→prepare→実行」という流れ全体を配列ごとにループさせる(わかりやすいけど、処理時間はかかる)
  • カッコ自体を複数に増やして一括INSERTできるような長いSQL文を生成する

投稿2018/06/04 02:26

maisumakun

総合スコア145183

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

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

kirin311

2018/06/04 02:34

ありがとうございます。 sazi様の参考URL通り、カッコ自体を複数に増やして一括Insertという形がよさそうですね。 処理時間かかるのはきついです
guest

0

ベストアンサー

どうしても失敗した場合Falseが返ってきて

エラーメッセージを確認しましょう。
おそらくカラム数と値が合っていないというエラーになっているように思います。
SQLとして正しい文法かどうかは$sqlを出力して確認してみると分かります。

まとめて実行するためには下記のような形にする必要があります。

sql

1INSERT INTO tbl_name (col_name1, col_name2, ...) 2 VALUES (value1, value2, ...), (value1, value2, ...), (value1, value2, ...);

※cols部分は省略可能

上記、踏まえますと下記のようになるのでは。

php

1$values = []; 2foreach ($data as $rownum => $row) {//プレースホルダーの生成 3 $rowvalues = []; 4 foreach ($row as $column => $value) { 5 $rowvalues[] = ':' . $column.$rownum; 6 } 7 $values[] = '('.implode(',',$rowvalues).')'; 8} 9$sql = sprintf("INSERT INTO %s VALUES %s",$this->table_name,implode(',', $values)); 10 11echo $sql;

※個人的に変数名称はきちん意味を与えたいので修正してあります。

bindValueのところも同じように$column.$rownumに対して$valueを指定する形であわせてください。

投稿2018/06/04 02:32

編集2018/06/04 02:34
m.ts10806

総合スコア80850

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

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

kirin311

2018/06/04 02:35

ソースコードありがとうございます。 参考にさせていただきます。
kirin311

2018/06/04 04:57

>>bindValueのところも同じように$column.$rownumに対して$valueを指定する形であわせてください。 とおっしゃられましたので、こちらのソースをコピーして少しだけ編集させていただきましたところ、Trueをとるようになりましたが、実際の $stmt->execute()の書き込みができないです。。 ※記事編集いたします
m.ts10806

2018/06/04 05:06 編集

$columnは中のforeachで入ってくるものなのでそのforeachから出してしまうと 最後の$columnしかとってきませんよ。全てのキーに対して値が割り振られません。 foreach ($data as $rownum => $row) {//プレースホルダーの生成 foreach ($row as $column => $value) { $stmt->bindValue(':' . $column.$row_num, $value); } }
kirin311

2018/06/04 05:13

ありがとうございます。修正させていただきました。
m.ts10806

2018/06/04 05:38

コメント修正していますが、bindValueはセットするだけなので返却値を受け取らなくても良いです。 > $bool_value[] =
kirin311

2018/06/04 05:46

ありがとうございます。こちらの確認用としていれておりました。 SQL文は、問題なくbindValueもすべてTrueなのにexecuteが出来ない原因について調べているのですが・・
m.ts10806

2018/06/04 06:18

エラーメッセージがでているのでしたら略さずにそのままご提示ください。
kirin311

2018/06/04 06:24

エラーメッセージの表示とはどのようにしたら良いでしょうか? var_dumpで表示される簡易チェックとSQL構文と、booleanだけでそれらしきものが見当たらないです・・
m.ts10806

2018/06/04 06:43

ん、ああ、エラーが何かしらでているかと思ったのですが。 もし既に最初の1件目が入っている状態で同じ情報をinsertしようとしているのであれば、重複キーのエラーが出ていそうに思いました。 状況が良く分かりませんので、現在のデータの状態も踏まえて追記してください。 あとはtry-catchできちんとエラーハンドリングやったほうがいいかもしれませんね。 http://php.net/manual/ja/pdo.error-handling.php
kirin311

2018/06/04 06:55

現在のデータは、特に入っていないです。 カラムは同じにしてデータは空の状態です。 try-catch使ってみましたが、特にエラー発生しないですね・・ Tryは、
kirin311

2018/06/04 06:58

URL先の内容をそのままでやりましたがこれで良かったのでしょうか
kirin311

2018/06/04 07:37

$resultをvar_dump()しましたところ、boolean falseになります。 トランザクションとコミット入れてみます
kirin311

2018/06/04 07:55

errorinfo追加いたしましたが、URL先の例の出力通りにならない状態です・・
m.ts10806

2018/06/04 08:01 編集

何が起きたのでしょうか? 実行SQLでエラーがでているので書かなきゃいけないのはexecute()の直後では、と思うのですが。 > PDO::errorInfo() は、 このデータベースハンドラによって実行された直近の操作に関するエラー情報を 配列として返します。 つまりエラーが起きていない箇所で入れても意味がありません。
kirin311

2018/06/04 08:04

そういうことでしたか。 しかしecexute()直後でもエラーは何も起きていないです。 boolean falseです・・
kirin311

2018/06/04 08:10

$result = $stmt->execute();//データベースに書き込み実行する if (!$result) { echo "\nPDO::errorInfo():\n"; print_r($stmt->errorInfo()); } で試したところ、PDO::errorInfo(): Array ( [0] => HY093 [1] => [2] => ) となりました。
kirin311

2018/06/04 08:12

これは、ホルダーが間違っているということでしょうか・・?
m.ts10806

2018/06/04 08:14

HY093は SQLSTATE[HY093]: Invalid parameter number: parameter was not defined ですね。 用意されたパラメータに対してセットされているパラメータ・値が合っていないようです。 $stmt->bindValue(':' . $column . $row_num, $value);のところに下記のように入れて SQL文生成時に設定したパラメータの名前と値がそれぞれきちんと全て設定されているか確認してみてください。 echo ":{$column}{$row_num}=>$value <br />" ;
kirin311

2018/06/04 08:21

ありがとうございます、確認しましたところ最後の配列のほうに空白が出ていますね・・。 IF文で配列の中身が空白時は除外するみたいな処理を行ったほうが良さそうかな・・
m.ts10806

2018/06/04 08:24

どのカラムかにもよりますが、パラメータの数を合わせてデータの整合性さえ取りさえすれば解決するので、どうするかは検討してみてください。
kirin311

2018/06/04 08:28

ありがとうございます、検討してみます。
m.ts10806

2018/06/04 08:31

解決されたようで何よりです
kirin311

2018/06/04 08:36

そちらの都合もあるのに、こちらの都合で11時からこの時間まで回答ありがとうございます。 ものすごく困っておりましたが、解決の目途が立ちそうでとても助かりました。 ベストアンサーとさせていただきます。
m.ts10806

2018/06/04 08:56

いえいえ ハマると何時間、何日も同じ問題から抜け出せなくなるのが常なので、少しでも早い解決の手助けになったのでしたら良かったです。 デバッグの方法は色々とあるので、今回のアドバイスを機に様々な角度から検証してみて解決に至れるようにがんばってみてください。
guest

0

投稿2018/06/04 02:19

sazi

総合スコア25184

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問