我正在将.csv文件导入MySQL,一切正常,除了文件中的换行符。
我的一个.csv行看起来像这样:
42,E-A-R™ Classic™ Earplugs,ear,images/ear/classic.jpg,5%,"Proven size, shape, and foam
3M's most popular earplug
Corded and uncorded in a variety of individual packs
NRR 29 dB / CSA Class AL",312-1201,,"E-A-R™ Classic™ Uncorded Earplugs, in Poly Bag",310-1001,,E-A-R™ Classic™ Uncorded Earplugs in Pillow Pack,311-1101,,"E-A-R™ Classic™ Corded Earplugs, in Poly Bag"
第六个字段应该在调用时进入一个新行,但事实并非如此。导入.csv时,我选择以 \ r \ n结尾的行。我试过\ n和auto但没有运气。
奇怪的是,该字段在数据库中看起来是正确的,具有所有适当的中断。如果我手动进入PHPmyadmin插入换行符,它会正确打印。每个字段也设置为UTF-8。
有关于此的任何想法吗?感谢。
编辑:这是MySQL声明
LOAD DATA LOCAL INFILE '/tmp/php89FC0F' REPLACE INTO TABLE `ohes_flyer_products`
FIELDS TERMINATED BY ','
ENCLOSED BY '"'
ESCAPED BY '\\'
LINES TERMINATED BY '\r'
答案 0 :(得分:11)
LOAD DATA LOCAL INFILE '/tmp/php89FC0F' REPLACE INTO TABLE `ohes_flyer_products`
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
ESCAPED BY '\\'
LINES TERMINATED BY '\r\n'
答案 1 :(得分:3)
也许您可以使用fgetcsv将每个csv行解析成一个数组,然后将该数组转储到数据库中?
的内容
$fd = fopen($csvfile, "r");
while ($line = fgetcsv($fd))
{
$sql = sprintf("INSERT INTO tablename (...) VALUES ('%s', ...)", $line[0], ...);
$res = mysql_query($sql);
}
注1:代码尚未准备好生产,请检查SQL注入!
注意2:请使用预处理语句,因为使用它们会使事情变得很快(或者制作一个多行插入语句)。
注3:在事务中包装所有。
答案 2 :(得分:1)
您的CSV文件具有一些您可以利用的品质。
了解这一点,您可以尝试以下方法:
使用UltraEdit(或Notepad ++)等程序及其查找/替换功能(包括正则表达式处理):
假设回车出现在由分隔符(引号)括起来的字段中,您可以指定导入引擎应该只接受字段并记录引用之外的分隔符。 (MySQL LOAD DATA INFILE syntax)具体来说,请查看ENCLOSED BY 'char'
参数。由于并非所有字段都使用分隔符,因此您需要指定OPTIONALLY
。理论上,您应该能够指定CSV文件的构造方式,而不需要事先解析它。不过,我认为应该删除现场回车,以便在新环境下输出时文本将正确包装。
答案 3 :(得分:0)
您的CSV似乎是非标准的,但这通常是处理客户数据集的现实。
由于像MySQL的LOAD DATA语句这样的工具只能处理完美的用例,我发现处理这样的非标准数据集需要代码。
处理此问题的一种方法是首先清理CSV,使用特殊的唯一字符串(如===MIDFIELD_LINE_BREAK===
)替换中间字段换行符。然后我会用脚本语言(Python,Ruby,PHP,Perl等)编写自定义CSV解析器。
在CSV解析器中,遍历文件中的行。对于每一行:
\n
或\r
个字符重新换成===MIDFIELD_LINE_BREAK===
个字符。答案 4 :(得分:0)
这对我有用:
$query = <<<EOT
LOAD DATA LOCAL INFILE '$file' REPLACE INTO TABLE `$table`
FIELDS TERMINATED BY ','
OPTIONALLY ENCLOSED BY '"'
ESCAPED BY '\\\'
LINES TERMINATED BY '\\\n'
IGNORE 1 ROWS;
EOT;
我不得不通过添加一些额外的正斜杠来调整@Krunal的答案,因为会出错。
顺便说一下,这里使用了Unix行返回。
DOS: \\\r\\\n
Old Mac: \\\r
Unix: \\\n