从CSV到MySQL的换行问题

时间:2011-01-13 17:12:07

标签: php mysql line-breaks

我正在将.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'

5 个答案:

答案 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文件具有一些您可以利用的品质。

  • 包含终止记录的回车符的字段用引号括起来。
  • 表示记录结束的回车符跟在一个记录中,数据用引号括起来。如果对于所有记录都是如此,则可以将中间字段回车与记录终止符区分开来。

了解这一点,您可以尝试以下方法:

  1. 使用UltraEdit(或Notepad ++)等程序及其查找/替换功能(包括正则表达式处理):

    • 查找以引号开头的所有回车,并用唯一的字符或字符串替换它们。我建议管道字符“|”但首先要确保它们不会在CSV文件中的任何位置使用。这些将代表记录结束。
    • 接下来,用空格替换所有回车符。这将使带有不需要的回车的字段重新与其他数据保持一致。
    • 最后,用回车替换所有特殊的记录结束字符。唯一的回车存在的最终结果是记录结束指标。
  2. 假设回车出现在由分隔符(引号)括起来的字段中,您可以指定导入引擎应该只接受字段并记录引用之外的分隔符。 (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===个字符。
  • 构造并执行INSERT语句。

答案 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