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

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

ただいまの
回答率

90.34%

  • PHP

    25526questions

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

  • MySQL

    7428questions

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

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

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 3,252

smnsmn

score 170

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

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

100 鈴木
101 田中
102 山田

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

$data = array('id' => array('101', '102', '103'),
       ('name' => array('鈴木', '田中', '山田');

$data = array('id' => array('101' => array('name' => '鈴木'),
              '102' => array('name' => '田中'),
              '103' => array('name' => '山田')
        );

どれもイマイチ違うように思います・・・。

クエリとしては下記で良いのでしょうか?(PHP上で実行します。)

$query = "INSERT INTO hoge (id, name) "
    ."VALUES ("
    ."'".$data."'" 
    ")";

$result = mysql_query($query);

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

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

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

+1

$data = array(
    array(
        'id' => 101,
        'name' => '鈴木',
    ),
    array(
        'id' => 102,
        'name' => '田中',
    ),  
);

$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();


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

クエリ部分はプリペアドステートメントで構成し、全体をトランザクション(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パターン
$dbh  = new PDO('mysql:host=xxxxx;dbname=xxxxx;charset=utf8','xxxxx','xxxxx');
$stmt = $dbh->prepare("INSERT INTO hoge (id, name) VALUES (:id, :name)");

$dbh->beginTransaction();
foreach($data as $datum) {
    $stmt->bindValue(':id', $datum['id'], PDO::PARAM_INT);
    $stmt->bindValue(':name', $datum['name'], PDO::PARAM_STR);
    $stmt->execute();
}
$dbh->commit();


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

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/02 16:17

    回答に追記しました。

    キャンセル

  • 2016/03/02 17:34

    ありがとうございます。
    徐々にですが理解できました。

    $datumをforeachで作っていますがその後使用しないのでしょうか?;;;
    >しません。使えないわけではないですが、多くの場合foreachの外では使い道はありません。

    少し勘違いしておりました。
    foreach($data as $datum)内で$dataを$datumに入れ、
    $id にid、$nameにnameを代入し、

    バインドで:idの名前がついている箇所に変数$idを紐づけているので
    最後に$stmt->execute();でSQL実行・・・

    といった感じでしょうか。;;;
    先にバインドしているので、その後で$idなどに値を代入するだけで良いのですね・・・・。

    とても勉強になりました!
    ありがとうございますm(__)m

    キャンセル

  • 2016/03/02 17:53

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

    キャンセル

+1

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

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

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

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

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

// クエリ生成
$query  = "INSERT INTO `hoge` (`id`, `name`) ";
$query .= "VALUES " . implode("," ,array_fill(0, count($data), "(?, ?)"));

// この場合は、クエリ投げる用の配列を別途整形する必要があります
$value = array(101, "鈴木", 102, "田中"); // …という形になるはず

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/02 16:04

    ご回答ありがとうございます。
    なるほど、配列に入れた値をinsert文に全部記述してしまうのですね。

    >// この場合は、クエリ投げる用の配列を別途整形する必要があります
     $value = array(101, "鈴木", 102, "田中"); // …という形になるはず

    これはどういう意味でしょうか?;;
    $dataとは別に$valueが必要ということでしょうか?
    $queryの中で$valueは出てきていないと思いまうすが、何に必要なのでしょうか?

    よろしければご教授いただけませんでしょうか。mm

    キャンセル

  • 2016/03/02 17:36

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

    キャンセル

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

  • ただいまの回答率 90.34%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • PHP

    25526questions

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

  • MySQL

    7428questions

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