【问题标题】:Line break issue from CSV to MySQL从 CSV 到 MySQL 的换行问题
【发布时间】:2011-01-13 17:12:07
【问题描述】:

我正在将一个 .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 时,我选择 Lines terminate by \r。我试过 \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'

【问题讨论】:

  • 你最初想导入什么,phpMyAdmin 还是控制台 mysql?
  • 我假设您的意思是第 6 个字段,以“已验证的大小...”开头。
  • 您能否也发布您使用的确切 MySQL LOAD DATA 语句?
  • 我遇到了相反的问题,我从 MySql 导出数据以在 Excel 中用于报告,而包含内部换行符的字段会导致行换行,从而生成一个包含数据的新行应该包含在前一行中。我的解决方案是使用竖线 (|) 字符进行换行,并在使用前在文本编辑器中转换所有内容。
  • MySQL 语句现在在主帖中,我正在使用 phpMyAdmin 导入。

标签: php mysql line-breaks


【解决方案1】:
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'

【讨论】:

    【解决方案2】:

    也许您可以使用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:将所有内容包装在一个事务中。

    【讨论】:

      【解决方案3】:

      您的 CSV 文件具有一些您可以利用的特性。

      • 包含终止记录的回车的字段用引号引起来。
      • 表示记录结束的回车符跟在数据用引号括起来的记录之后。如果所有记录都是如此,则可能是一种区分中间字段回车符和记录终止符的方法。

      知道了这一点,您可以尝试以下几点:

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

        • 查找前面带引号的所有回车并将其替换为唯一字符或字符串。我建议使用管道字符“|”但首先确保它们没有在 CSV 文件中的任何地方使用。这些将代表记录结束。
        • 接下来,将所有回车替换为空格。这将使带有不需要的回车的字段重新与其他数据对齐。
        • 最后,用回车替换所有特殊的记录结束字符。唯一存在的回车的最终结果是记录结束指示符。
      2. 鉴于回车出现在由分隔符(引号)括起来的字段中,您可以指定导入引擎只应遵循引号外部的字段和记录分隔符. (MySQL LOAD DATA INFILE syntax) 具体看ENCLOSED BY 'char'参数。由于并非所有字段都使用分隔符,因此您需要指定 OPTIONALLY。理论上,您应该能够指定 CSV 文件的构造方式,而无需事先对其进行解析。但是,我认为应该删除字段内回车符,以便在新上下文中输出时文本将正确换行。

      【讨论】:

        【解决方案4】:

        您的 CSV 似乎是非标准的,但这通常是处理客户数据集的实际情况。

        由于像 MySQL 的 LOAD DATA 语句这样的工具只能处理完美的用例,我发现处理这样的非标准数据集需要代码。

        解决此问题的一种方法是首先清理您的 CSV,用特殊的唯一字符串(如 ===MIDFIELD_LINE_BREAK===)替换中场换行符。然后我会用脚本语言(Python、Ruby、PHP、Perl 等)编写一个自定义的 CSV 解析器。

        在您的 CSV 解析器中,遍历文件中的行。对于每一行:

        • \n\r 字符换回===MIDFIELD_LINE_BREAK=== 字符。
        • 构造并执行 INSERT 语句。

        【讨论】:

        • 这听起来可行,但仍然需要手动输入 ===MIDFIELD_LINE_BREAK===。相反,我手动输入了 \n ,它似乎工作。无论如何,谢谢。
        • 我应该指定当我说“擦洗”时,我的意思是它是基于规则的自动擦洗(即join the next line until there are X unescaped/uncontained commas)。我不知道您的数据集小到无法手动清理,但我很高兴它对您有用!
        【解决方案5】:

        这对我有用:

        $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
        

        【讨论】:

          猜你喜欢
          • 2011-09-05
          • 2016-03-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2012-08-05
          • 1970-01-01
          相关资源
          最近更新 更多