人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

MySQLの質問
CSVのデータをMySQLに移そうと思ったのですが連続してデータを挿入する方法がわかりません。
for文でSQLを発行しようとしても1行で止まってしまいます。

処理の大まかな流れは
CSVファイル読み込み
foreach{
DBにコネクト
insert文
DB切断


こんな感じです。
DBコネクトと切断をforの外に出しても結果は同じでした・・・

言語はperlが好ましいですがPHPでもかまいません。


●質問者: pipi_n
●カテゴリ:ウェブ制作
✍キーワード:CSV dB MySQL Perl PHP
○ 状態 :終了
└ 回答数 : 5/5件

▽最新の回答へ

1 ● きゃづみぃ
●20ポイント

一般的に考えられるロジックは、以下のとおりです。

DBにコネクト(トランザクション開始)

CSVファイル オープン

ループ開始

CSVファイルから1行目を読み込み

最終行なら 終了処理へ

INSERT文

ループ開始へ戻る

終了処理

コミット発行

DB切断

エラー時

ロールバック

DB切断

◎質問者からの返答

ロジックはその通りなんですよね。

そのロジックでも試してみたのですがダメでした・・・


2 ● いのくに
●50ポイント

「load data infile」という便利なSQL文の使用を検討されてみてはいかがですか?

http://dev.mysql.com/doc/refman/4.1/ja/load-data.html

load data infile 'ファイル名' into table テーブル名 fields terminated by '区切り文字' lines terminated by '改行記号';

◎質問者からの返答

おぉ!そんな命令があるのですね!

試してみます。

試した結果・・・うまくいかなかったです・・・

下記のソースで「接続失敗2」で止まってしまいます。

use DBI;

print "Content-type: text/html\n\n";

print "<html>";

print "接続
\n";

# DBに接続

$db = DBI->connect("DBI:mysql:DB名:ホスト名","ID","PASS");

if(!$db){

print "接続失敗1\n";

exit;

}

$sth = $db->prepare("load data infile 'in.txt' into table test fields terminated by ',' lines terminated by '\r\n'");

if(!$sth->execute){

print "接続失敗2\n";

exit;

}

# ステートメントハンドルクリア

$sth->finishi;

# DB切断

$db->disconnect;

print "処理終了

\n";


3 ● くいっぱ
●20ポイント

PHPですが、こんな感じです。

トランザクションを使用していませんが、つかうなら、takntさんがご指定のような位置がベストかと思います。


手元にあったcsvのアッププログラムから共通関数やらなにやらを消して簡略化したものですが…

<?php
$tmp_file_path = $_FILES['upfile']['tmp_name'];
if ($tmp_file_path == "") {
die("ファイルが指定されていません");
}
// DB Connect
gfDBConn($conn);
$handle = fopen($tmp_file_path, "r");
if ($handle) {
while (!feof($handle)) {
$buffer = fgets($handle, 4096);
$pieces = explode(",", $buffer);
if ($pieces[1] != "" ) {
// DB Insert
fInsStockMst($pieces[1] ,$pieces[3] ,$pieces[2]);
}
}
fclose($handle);
}
// MySQL 切断
mysql_close($conn);
print("完了<br><a href=./index.php>もどる</a>");
// DB接続
function gfDBConn(&$conn) {
global $pcDBname,$pcMySqlUser,$pcMySqlPass,$pcDatenbankname;
$conn = mysql_connect($pcDBname,$pcMySqlUser,$pcMySqlPass);
mysql_select_db($pcDatenbankname,$conn);
}
// 登録処理
function fInsStockMst($stock_cd ,$stock_nm ,$market_cd) {
global $conn;
$sSQL = "";
$sSQL .= "insert into stock_mst (";
$sSQL .= "stock_cd,";
$sSQL .= "stock_nm,";
$sSQL .= "market_cd,";
$sSQL .= "upddate,";
$sSQL .= "insdate";
$sSQL .= ") values (";
$sSQL .= " '".gfFixUpStr($stock_cd)."',";
$sSQL .= " '".gfFixUpStr($stock_nm)."',";
$sSQL .= " '".gfFixUpStr($market_cd)."',";
$sSQL .= "now(),";
$sSQL .= "now()";
$sSQL .= ") ";
$sSQL .= "ON DUPLICATE KEY UPDATE ";
$sSQL .= "market_cd4 = if(market_cd3 <> '','".gfFixUpStr($market_cd)."',''), ";
$sSQL .= "market_cd3 = if(market_cd2 <> '','".gfFixUpStr($market_cd)."',''), ";
$sSQL .= "market_cd2 = if(market_cd <> '','".gfFixUpStr($market_cd)."','') ";
$res = gfGetDBRs($sSQL, $conn);
}
// 入力を表示文字列からDB格納型へ
function gfFixUpStr($getstr,$rnflg=0,$maxlen=0) {
// サニタイズやらなにやら
$str = $getstr;
return $str;
}
?>
◎質問者からの返答

ソースまで書いて頂きありがとうございます。

しかし「PHPでもかまいません」とは書いたものの、PHPはあまり得意ではないのでkuippaさんが書いてくれたソースがいまいち理解できないでいます。

inokuniさんが教えてくれた命令で試して、どうしてもダメならkuippaさんのソースを解析して試してみようと思います。


4 ● いのくに
●50ポイント

$sth = $db->prepare("load data infile 'in.txt' into table test fields terminated by ',' lines terminated by '\r\n'");

in.txt の位置を相対パスではなく、絶対パスで記述する必要があります。

例: /home/user001/in.txt

あと、そのファイルがサーバ側にあるのか、クライアント側にあるのか?

クライアント側にあるのであれば、

load data local infile "/home/user001/in.txt" ...

と「LOCAL」を付与しなければなりません。

◎質問者からの返答

in.txtは同一サーバ上にあります。

絶対パスで指定してlocalも付けたり消したりを試してみたのですがダメでした。

「接続失敗2」で止まってしまいます。

ちなみにバージョンはMySQL 4.0.24です。

load data infile が使えないバージョンだったら笑い話にもならないですが・・・

$sth = $db->prepare("load data infile '/usr/home/・・・/in.txt' into table test fields terminated by ',' lines terminated by '\n'");


5 ● いのくに
●50ポイント

私の場合は下記のSQL文でうまくいっています。

LOAD DATA LOCAL INFILE "/home/user001/in.txt" INTO TABLE testtable FIELDS TERMINATED BY ',' ENCLOSED BY '"' (field1, field2, field3, field4);

各フィールドの型とか合ってるんでしょうかね?

あとは、エラーの原因を突き止めるしかないと思うので、

$dbh = DBI->connect($data_source, $username, $password) || die $DBI::errstr;

$sth = $dbh->prepare("load data infile '/usr/home/・・・/in.txt' into table test fields terminated by ',' lines terminated by '\n'")|| die $dbh->errstr;

$rv = $sth->execute || die $sth->errstr;

という感じで、errstrを参照してみてください。

◎質問者からの返答

perlからではなく、phpMyAdminからSQLを実行してみたらできました!

なぜperlからはできないのでしょう・・・

パスが通っていないのかな?う?ん・・・

ということで今回はphpMyAdminからできたからOKとしますが、今後のこともあるのでerrstrで原因を追及してみたいと思います。

(使い方わからないから調べなきゃ)

inokuniさん、ほんとうにありがとうございました!

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ