私はそのような.csvファイルデータを持っています
Date,Name,Call Type,Number,Duration,Address,PostalCode,City,State,Country,Latitude,Longitude
"Sep-18-2013 01:53:45 PM","Unknown","outgoing call",'123456',"0 Secs","null","null","null","null","null",0.0,0.0,,,
"Sep-18-2013 01:54:14 PM","Unknown","outgoing call",'1234567890',"0 Secs","null","null","null","null","null",0.0,0.0,,,
"Sep-18-2013 01:54:37 PM","Unknown","outgoing call",'14772580369',"1 Secs","null","null","null","null","null",0.0,0.0,,,
そして、私は次のコードを使用してデータベースにデータを挿入しています
$sql = "LOAD DATA INFILE `detection.csv`
INTO TABLE `calldetections`
FIELDS TERMINATED BY '".@mysql_escape_string(",").
"` OPTIONALLY ENCLOSED BY `".@mysql_escape_string("\"").
"` OPTIONALLY ENCLOSED BY `".@mysql_escape_string("\'").
"` ESCAPED BY `".@mysql_escape_string("\\").
"` LINES TERMINATED BY `".",,,\\r\\n".
"`IGNORE 1 LINES `"
."(`date`,`name`,`type`,`number`,`duration`,`addr`,`pin`,`city`,`state`,`country`,`lat`,`log`)";
$res = @mysql_query($con,$sql);
しかし、何も挿入されません。間違いはどこですか?
実行する前にecho($sql);
を実行すると、次の理由でクエリの構文が正しくないことがわかります。
ファイル名は、識別子ではなく文字列リテラルであるため、バッククォートではなく引用符で囲む必要があります。
_FIELDS TERMINATED BY
_および_ENCLOSED BY
_および_ESCAPED BY
_句で区切り文字を指定するためにmysql_escape_string()
を呼び出す必要はまったくありません。
バックティックを使いすぎます。実際、あなたの場合、予約語は使用されていないため、すべてを捨てます。煩雑になるだけです。
CSVファイルの最初の行の最後に持っている必要があります _,,,
_を使用しているのは、これらを行区切り文字の一部として使用しているためです。そうしない場合は、最初の行だけでなく、データを含む2番目の行もスキップします。
_ENCLOSED BY
_句を複数回使用することはできません。 Number
フィールドを別の方法で処理する必要があります。
サンプル行を見ると、_ESCAPED BY
_は必要ありません。ただし、必要な場合は、この_ESCAPED BY '\\'
_のように使用してください。
構文的に正しいと言われていることは、このように見えるかもしれません
_LOAD DATA INFILE 'detection.csv'
INTO TABLE calldetections
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY ',,,\r\n'
IGNORE 1 LINES
(date, name, type, number, duration, addr, pin, city, state, country, lat, log)
_
ここで、ロード中にかなりの数のフィールドを変換する必要があります。
テーブル内のdate
がdatetime
データ型の場合、変換する必要があります。そうでない場合はエラーが発生します
誤った日時値:行の列 'date'の 'Sep-18-2013 01:53:45 PM'
Number
フィールドの値を囲む単一のqoutesを処理する必要があります
_"null"
_列の実際のNULL
に_addr, pin, city, state, country
_文字列リテラルを変更する可能性が高い
期間が常に秒単位の場合、秒の整数値を抽出し、それをテーブルにそのように保存して、後で期間値を簡単に集計できるようにすることができます。
つまり、ステートメントの有用なバージョンは次のようになります。
_LOAD DATA INFILE 'detection.csv'
INTO TABLE calldetections
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY ',,,\r\n'
IGNORE 1 LINES
(@date, name, type, @number, @duration, @addr, @pin, @city, @state, @country, lat, log)
SET date = STR_TO_DATE(@date, '%b-%d-%Y %h:%i:%s %p'),
number = TRIM(BOTH '\'' FROM @number),
duration = 1 * TRIM(TRAILING 'Secs' FROM @duration),
addr = NULLIF(@addr, 'null'),
pin = NULLIF(@pin, 'null'),
city = NULLIF(@city, 'null'),
state = NULLIF(@state, 'null'),
country = NULLIF(@country, 'null')
_
以下は私のマシンでクエリを実行した結果です
mysql> LOAD DATA INFILE '/tmp/detection.csv' -> INTO TABLE calldetections -> FIELDS TERMINATED BY'、 ' -> OPTIONALLY ENCLOSED BY '"' -> LINES TERMINATED BY ',\n' -> 1行を無視 ->(@date、name、type、@number、@ duration、@ addr、@ pin、@ city、@ state、@ country、lat、log) -> SET date = STR_TO_DATE(@date、 '%b-%d-%Y%h:%i :%s%p ')、 -> number = TRIM(BOTH'\'' FROM @number)、 -> duration = 1 * TRIM(TRAILING 'Secs' FROM @duration) 、 -> addr = NULLIF(@addr、 'null')、 -> pin = NULLIF(@pin、 'null')、 -> city = NULLIF( @city、 'null')、 -> state = NULLIF(@state、 'null')、 -> country = NULLIF(@country、 'null'); クエリOK、影響を受ける3行(0.00秒) レコード:3削除:0スキップ:0警告:0 mysql> select * from calldetections; + --------------------- + --------- + --------------- +- ------------ + ---------- + ------ + ------ + ------ + ----- -+ --------- + ------ + ------ + |日付|名前|タイプ|番号|期間| addr |ピン|市|状態|国| lat |ログ| + --------------------- + --------- + ---------- ----- + ------------- + ---------- + ------ + ------ + ----- -+ ------- + --------- + ------ + ------ + | 2013-09-18 13:53:45 |不明|発信通話| 123456 | 0 | NULL | NULL | NULL | NULL | NULL | 0.0 | 0.0 | | 2013-09-18 13:54:14 |不明|発信通話| 1234567890 | 0 | NULL | NULL | NULL | NULL | NULL | 0.0 | 0.0 | | 2013-09-18 13:54:37 |不明|発信通話| 14772580369 | 1 | NULL | NULL | NULL | NULL | NULL | 0.0 | 0.0 | + --------------------- + --------- + ---------- ----- + ------------- + ---------- + ------ + ------ + ----- -+ ------- + --------- + ------ + ------ + 3行セット(0.00秒)
最後に、PHPで_$sql
_変数にクエリ文字列を割り当てると、次のようになります。
_$sql = "LOAD DATA INFILE 'detection.csv'
INTO TABLE calldetections
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '\"'
LINES TERMINATED BY ',,,\\r\\n'
IGNORE 1 LINES
(@date, name, type, @number, @duration, @addr, @pin, @city, @state, @country, lat, log)
SET date = STR_TO_DATE(@date, '%b-%d-%Y %h:%i:%s %p'),
number = TRIM(BOTH '\'' FROM @number),
duration = 1 * TRIM(TRAILING 'Secs' FROM @duration),
addr = NULLIF(@addr, 'null'),
pin = NULLIF(@pin, 'null'),
city = NULLIF(@city, 'null'),
state = NULLIF(@state, 'null'),
country = NULLIF(@country, 'null') ";
_
mysqli_query($cons, '
LOAD DATA LOCAL INFILE "'.$file.'"
INTO TABLE tablename
FIELDS TERMINATED by \',\'
LINES TERMINATED BY \'\n\'
IGNORE 1 LINES
(isbn10,isbn13,price,discount,free_stock,report,report_date)
SET RRP = IF(discount = 0.00,price-price * 45/100,IF(discount = 0.01,price,IF(discount != 0.00,price-price * discount/100,@RRP))),
RRP_nl = RRP * 1.44 + 8,
RRP_bl = RRP * 1.44 + 8,
ID = NULL
')or die(mysqli_error());
$affected = (int) (mysqli_affected_rows($cons))-1;
$log->lwrite('Inventory.CSV to database:'. $affected.' record inserted successfully.');
RRPとRRP_nlとRRP_blはcsvにはありませんが、それを計算して挿入した後です。