• ベストアンサー

PHPでCSVを読み込みMySQLに行追加・変更

PHPでCSVファイルを読み込み、MySQLにデータを追加する方法を教えてください。 その際に、新規の行はIDを指定せず、auto_incrementでidを設定するようにして、IDを指定した場合は、既存の行を変更するようにしたいです。 また、prepareメソッドを用いたいです。 よろしくお願いします。

  • h_mp
  • お礼率97% (67/69)
  • PHP
  • 回答数6
  • ありがとう数12

質問者が選んだベストアンサー

  • ベストアンサー
noname#244856
noname#244856
回答No.2

日本語におかしなところがあるので、以下のように解釈して回答します。違う点があれば補足してください。 ・CSVファイル中に全てIDは含まれている。 ・データベース中に存在しないIDの場合は新規作成する。 ・データベース中に存在したIDの場合は変更する。 ---------------------------- 「REPLACE INTO」を使えばSQL1文でいけます。 <?php // データベース情報 $dsn = 'mysql:dbname=mydb;host=localhost;charset=utf8'; $username = 'root'; $password = ''; // ファイル名 $filename = 'data.csv'; try { // ファイルを読み込んでCSVとして読み取るモードに設定 $file = new \SplFileObject($filename); $file->setFlags(\SplFileObject::SKIP_EMPTY | \SplFileObject::DROP_NEW_LINE | \SplFileObject::READ_CSV); // データベースに接続して例外スローモードに設定 $pdo = new \PDO($dsn, $username, $password); $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION); // プリペアドステートメントを生成 $stmt = $pdo->prepare('REPLACE INTO table(a, b, c) VALUES(?, ?, ?)'); // 1行ずつ処理 foreach ($file as $row) $stmt->execute($row); } catch (\RuntimeException $e) { // エラー発生時はここにジャンプ echo 'Error: ' . $e->getMessage() . PHP_EOL; }

h_mp
質問者

お礼

ありがとうございます。 解釈された通りの内容でございます。 ファイルをアップロードしたものにする場合はどういった処理を行えばよろしいでしょうか。

その他の回答 (5)

noname#244856
noname#244856
回答No.6

MySQLの関数を使えばいいと思います。 http://www.w3schools.com/sql/func_now.asp データベースの種類に依存させたくないなら、PHPで現在日時を取得する方法もあります。好みで選んでください。 http://qiita.com/mpyw/items/e42fa173e5a26220a785

h_mp
質問者

お礼

ありがとうございます。 こちらも今後参考にさせていただきます。

noname#244856
noname#244856
回答No.5

ごめんなさい、変数名のwithとwithout入れ替えてください(転記ミス)

noname#244856
noname#244856
回答No.4

あ、やっぱりID欄が空欄になっているケースもあるんですね。質問文からは「存在しないIDを指定した場合」の挙動が読み取れなかったので、「本当はこういうことを言いたかったのかな?」とかなりエスパーっぽい解釈をするに至りました。(解釈と異なるなら補足が欲しかったです…) 強引にSQL1文でまとめようと思いましたが困難なようなので、素直にPHPで分岐させてSQL2文使います。 // ループ外でプリペアドステートメントを2つ作成しておく $stmt_with_id = $pdo->prepare('INSERT INTO (a, b) VALUES (?, ?)'); $stmt_without_id = $pdo->prepare('REPLACE INTO (id, a, b) VALUES (?, ?, ?)'); ... // $row[0]がIDのカラム if ($row[0] === '') { array_shift($row); $stmt_without_id->execute($row); } else { $stmt_with_id->execute($row); }

h_mp
質問者

お礼

ご丁寧に誠にありがとうございます。 また、解釈の違いについて気づかずに、補足できず申し訳ありませんでした。 こちらで、無事動きました。 それと、更新日時のカラムがあるのですが、できればそれに現在の日時を入れたいので、そちらの方法も教えていただけると幸いです。 よろしくお願いいたします。

noname#244856
noname#244856
回答No.3

↓のSQL文替えるだけで実現できそうです http://qiita.com/mpyw/items/caa2568284b69d270f8b

h_mp
質問者

お礼

ご回答ありがとうございます。 これでやってみたのですが、idが空の場合、「SQLSTATE[HY000]: General error: 1366 Incorrect integer value: '' for column 'id' at row 1」というエラーが出ます。 それと、更新日時のカラムがあるのですが、できればそれに現在の日時を設定したいので、そちらの方法も教えていただけると幸いです。 よろしくお願いいたします。

  • t_ohta
  • ベストアンサー率38% (5080/13275)
回答No.1

fgetcsv() を使えばCSVファイルから1行ずつ読み込んでデータを配列として受け取れます。 http://php.net/manual/ja/function.fgetcsv.php 後は配列のデータを見てIDがあればupdate、無ければinsertを発行するだけです。

h_mp
質問者

お礼

fgetcsv()を使えば、配列として受け取って処理ができるんですね。 大変勉強になります。 ありがとうございます。

関連するQ&A

  • PHP5+MySQL5 CSVから、更新、追加する処理の書き方

    こんにちは。 PHP5とMySQL5を使っています。 CSVファイルを読み込み、キーが存在するレコードは更新、 存在しなければ追加、という処理について 色々な書き方を教えて頂けたらと思います。 例えば、フィールドは、ユニークキーとなる[ID]、 [Name]、[TEL]の3つとします。 1.CSV読む 2.行と列の2次元配列に格納 3.行数分ループ開始 3-1.IDをキーに、SELECT 3-2.存在したら 3-3.UPDATE更新 3-2.存在しなかったら 3-3.INSERT追加 4.行数分ループ終了 と考えています。 CSVに100行あったら、100回SELECT掛けることになりますが、 この書き方で問題ないでしょうか? もっと判り易い、こんな書き方も! というのがありましたら、是非頂けますでしょうか。 よろしくお願いします。

    • ベストアンサー
    • PHP
  • MySQLでinsertした行を取得する

    table t1 id name ------- 1 aaa 2 asv 3 aae といったauto incrementのidを持ったテーブルt1を考えたときに mysql_queryで新規行をinsertした場合にそのidを取得するような ことはできるのでしょうか? phpのmanualを参考にしたところ出来ないような感じのことが書かれて いたのですが,このようなことは頻繁に必要な気もするのですが・・・ 既に考えた案としては ・auto incrementを外して最大のidの1つ上を指定してinsertする ・一度lockしてからinsertして最大のidを取得する というものです もっと1つの関数かなにかでスマートに書けたらいいのですが

    • ベストアンサー
    • PHP
  • 【PHP】csvファイルへの書き出し(1行追加or1行上書き)について

    【PHP】csvファイルへの書き出し(1行追加or1行上書き)について はじめて利用させていただきます。 現在、PHPにて書き出し処理を作成している者ですが、csvファイルへの書き出しの際に先頭行にスペースが大量に入ってしまい、困っています。 自分なりに調べてみたのですが、原因がわかりません。詳しい方からのアドバイスをお願いしたいです。 【行っている処理】 1.csvファイルを1行ずつ読み込み、配列に格納 2.既存のデータに同じ名前の人が存在する場合は、その行の配列の内容を変更(存在しない場合は配列の末尾に1件追加) 4.現在ファイルにあるデータを削除(丸めこみ)し、配列データを書き書き出し 【ソース】(書き出し処理に問題があると思ったため、それ以外の部分は割愛させていただきます) <?php $filename = 'data.csv'; $file = fopen($filename, "r+" ); $name = array(); if(flock($file,LOCK_SH)){ while( $data = fgetcsv( $file, 1000, "," ) ) {   //配列に格納 } //配列の内容変更or新規に一行追加処理 //現在のファイル内のデータを削除(まるめこみ) ftruncate($file, 0); //1行分のデータをカンマ区切りで結合し、書き出し for($i = 0; $i < $count; $i++){ $ins = $name[$i]; $ins .= ','; $ins .= $number[$i]; //書き込み失敗時のエラー if(fwrite($file, "$ins\n" ) === FALSE){ print("ファイル書き込みに失敗しました"); }else{ //処理なし } } //ファイルロック解除 flock($file, LOCK_UN); }else{ print("ファイルロックに失敗しました"); } 【csvファイルの中身(処理実行前)】 佐藤,1234 田中,12345 中村,9876 【csvファイルの中身(処理実行後)】                       佐藤,1234 田中,12345 中村,9876 以上です。 よろしくお願いします。

    • ベストアンサー
    • PHP
  • csvファイルを使ってMySQLのテーブルを更新し

    約2万件ある15個のカラムで構成されるMySQLのテーブルがあります。 このテーブルをcsvファイルを使って更新しようと考えています。 csvファイルにはレコードIDとあるカラムの変更する値の2つのセルで 構成されています。 行数は毎回異なりますが、だいたい300行前後です。 csvファイルの具体的イメージはこんな感じです。 id order ============ 2,  200 4,  10 7,  460 11,  35 MySQLのテーブルの方にも「id」と「order」というカラムが存在します。 java や PHP を使ってやる方法はわかるんですが、プログラムを作成しないで SQLだけで行いたいと考えています。 LOAD DATA LOCAL INFILE などがあることがわかったのですが、レコードを REPLACE  するのではなく、一部のカラムをアップデートしたい、ということです。 どなたか、教えて頂けると助かります。 よろしくお願い致します。

  • mysqlでオートナンバーにするには?

    OSはRedhatLinux7.1 Apache_1.3.26 php-4.2.3 mysql-3.23.52 を使っています。 mysqlでデータ型をオートナンバー型にしたいのですが、何と指定すればいいのですか? postgreSQLではserialと指定するようなのですが。。。 auto_increment?ってゆーのでやってみたのですがエラーになってしまい先に進めません。 アドバイスお願いします。

  • PHPでCSVファイルの特定行のみ表示

    PHPでCSVファイルを読み込ませるにあたり、「クエリで指定した特定の1行だけ」を取りだしたいと考えています。 下記だと、1行目からクエリで指定した特定行までの抽出が可能です。 hoge.php?repert=5  → 1から5行目までが表示される。 従い、下記から特定行より上の行を削除すれば、当方が考えている「クエリで指定した特定の1行だけ」を取りだすことになりますが、その方法がわかりません。 ご教示いただきたくお願いいたします。 <?php $repeat = $_GET['repert']; $fp = fopen("file2.csv", "r"); $count = 1; while ($data = fgetcsv($fp, 10000)) { if ($count > $repeat) { break; } print <<<EOD $data[0]・$data[1]・$data[2]<br> EOD; $count++; } fclose ($fp) ?>

    • ベストアンサー
    • PHP
  • PHPでMySQLに格納したファイルをダウンロードしたいです。

    MySQLサーバに格納したファイルをPHPを使ってブラウザからファイルをダウンロードするプログラムを作りたいのですが、やり方が分からず困っています。方法もしくは簡単なスクリプトを教えてください。お願いします。 PHPを使ってブラウザからMySQLに画像やファイルをアップロードできたのですが、取り出す方法が分かりません。バイナリデータを取り出してimage srcを用い、ブラウザに画像を表示するまではできました。 テーブルは create table image( ID int not null primary key auto_increment, data MEDIUMBLOB); で作成しています。 ご教授お願いします。

    • ベストアンサー
    • PHP
  • mysqlへの書き込みがリロードする度に行われてしまう。

    現在PHPとMYSQLを使ってサイトを作っています。 そこで、テーブルの追加をinsert文を使って実行し、 追加されたテーブルをselect文で表示させるということをやっています。 現在はhoge.htmlでフォーム側を記載し、hogehoge.phpで受け取り、データを追加、表示させるようにしています。 登録作業の方は問題なく実行されるのですが、 登録されたデータがhogehoge.phpをリロードする度に永遠と同じデータが追加され続けてしまう現象がおきています。(auto_incrementに指定しているidだけがかわる) データを登録し終わると次にリロードしてもデータが追加されないようにするにはどのようにすればよいのでしょうか。 ご教授御願いいたします。

  • 【PHP】CSVファイルの特定行を書き出す

    PHPでCSVファイルを読み込み、特定行のみを別のCSVファイルに書き出したいと思います。 作りたいものは、 http://example.com/file.php?repert=5 とすると、「002.csvファイルの5行目のみ」を「003.csv」に書き込むというものです。 下記で作りましたが、 Parse error: syntax error, unexpected end of file in C:\xampp\htdocs\file.php on line 32 になります。 指摘された32行は ?> の行です。 ググると改行コードのトラブルのようでしたのでCR+LF CR LF と試しましたが、改善されません。 どこが不味いかご教示戴けませんでしょうか? 宜しくお願い致します。 <?php $repeat = $_GET['repert']; $inFile = '002.csv'; // 抽出元ファイル $outFile = '003.csv'; // 結果ファイル $inFp = fopen($inFile, 'rb'); $outFp = fopen($outFile, 'w'); while ($data = fgetcsv($fp, 10000)) { if ($count == $repeat) { { $outLineArray = array( 0 => $data[0], 1 => $data[1], 2 => $data[2] ); fputs($outFp, implode(",", $outLineArray) . ""); } } fclose($inFp); fclose($outFp); exit(); ?>

    • 締切済み
    • PHP
  • csvファイルを読み込み→上書きするスクリプト【添削願】

    csvファイルを読み込み→上書きするスクリプトを作ってみましたがうまく行かないときがあり原因を考えています。 100行程度のcsvから任意の行($idで指定したもの)を書き換えたいのですが、(テスト書き込みを)書き込んでくれるときと指定したその行だけ削除されてしまうときとまちまちです。 なぜ2パターンの結果がでるのでしょうか? お力をお借りできると幸いです。 <?php //データの取り出し $id = $_GET['id']; $data = file("data/file.csv"); //idで指定した行に書き込み $data[$id] ="テスト書き込み"; //csvファイルにデータの書き込み $file = fopen("data/file.csv","w+"); flock($file, LOCK_EX); for($i=0; $i<count($data); $i++) { fwrite($file,$data[$i]); } fclose($file); ?>

    • ベストアンサー
    • PHP

専門家に質問してみよう