【问题标题】:Prevent LOAD DATA INFILE from escaping double double quotes防止 LOAD DATA INFILE 转义双双引号
【发布时间】:2016-02-13 14:03:05
【问题描述】:

我有如下 csv 数据:

"E12 98003";1085894;"HELLA";"8GS007949261";"";1
"5 3/4"";652493;"HELLA";"9HD140976001";"";1

某些字段包含在双引号中。问题是 正如您在第二行中看到的那样,第一列中的数据在末尾包含一个双引号作为数据的一部分。

我尝试了一些类似的方法:

LOAD DATA INFILE file.csv
INTO TABLE mytable
FIELDS TERMINATED BY ';' ENCLOSED BY '"'
LINES TERMINATED BY '\r\n'

但它会使用数据中的引号来转义包含引号的字段。我还尝试了ESCAPED BY ''ESCAPED BY '\\',但没有成功。 有没有办法阻止LOAD DATA INFILE 命令转义双双引号? 或者我应该解析csv并在只有一个时加上双引号? 无论如何,我正在使用 powershell 解析文件以将编码更改为 utf8。有什么方法可以快速解决这个问题吗?我的PowerShell代码:

function Convert-FileToUTF8 {

    param([string]$infile,
          [string]$outfile,
          [System.Int32]$encodingCode)

    $encoding = [System.Text.Encoding]::GetEncoding($encodingCode)
    $text = [System.IO.File]::ReadAllText($infile, $encoding)
    [System.IO.File]::WriteAllText($outfile, $text)

}

好的,我使用 .NET 正则表达式来修复 csv。这是昂贵的,但不是太多。 我写了

$text = [regex]::Replace($text, "(?m)(?<!^)(?<!\;)""(?!\;)(?!\r?$)", '""');

就在函数的最后一行之前,它似乎工作正常。由于我是正则表达式的新手,这可能会有所改进。

【问题讨论】:

  • 主要问题是输入数据是无效的CSV格式,因为属于数据的双引号应该已经加倍(转义)了。所以问题就变成了:你从哪里得到这个无效的 CSV,你能做些什么来修复它?
  • 它是从第三方软件导出的。不幸的是,我无法控制如何创建 csv。

标签: mysql csv escaping load-data-infile


【解决方案1】:

主要问题是输入数据构成无效的CSV语法,如RFC-4180第7段所述:

如果使用双引号将字段括起来,则出现在字段内的双引号必须通过在其前面加上另一个双引号来进行转义。

但是在您的 PowerShell 脚本中,您可以尝试使用 $text 上的 replace method 来解决这个问题,只要你得到它的值:

$text = $text.Replace('"";', '""";')

这应该足够了,因为如果未转义的双引号出现在数据的其他地方,加载程序将很好地处理它们,如mysql.com(我的亮点)所述:

如果字段以ENCLOSED BY 字符开头,则该字符的实例被识别为终止字段值仅当其后跟字段或行TERMINATED BY顺序。

当然,如果格式错误的 CSV 中有包含 "; 的数据,那么您仍然有问题。但是很难确定这种情况是否会终止数据或应该被视为数据的一部分,即使对于人类也是如此:-)

mysql.com 上发现的另一件事要注意:

如果输入值不必用引号括起来,请在 ENCLOSED BY 关键字之前使用 OPTIONALLY

【讨论】:

  • 恐怕您的解决方案只会处理数据末尾未转义的双引号。
  • 是的,但是 MySql Load 将按原样处理内部引号,即使未转义,条件是它们后面没有字段或行分隔符。
  • 看起来不错...不过,困扰我的是无法保证这种情况...
  • 用一些参考资料更新了我的答案。你是对的,如果 CSV 不是规范的,则所有保证都将丢失。 CSV 标准有充分的理由......
  • 我最后尝试使用正则表达式,但您的指导非常有帮助。
【解决方案2】:

另外:当使用 ENCLOSED BY 选项时,在 MySQL 中导入包含在引号中的值的 CSV 文件可以正常工作。除非包含的字段是一行中的最后一个字段,并且您使用 Excel 创建了 CSV 文件。 Excel 在一行中的最后一个字段之后省略了字段分隔符。 MySQL 不介意……除非最后一个字段用引号引起来。然后导入在该行终止。

示例:
这很好用: ...;value2;value3(没有尾随分隔符)
这也可以正常工作 ...;"value 2";value3(用引号括起来的值)
这也可以正常工作 ...;value 2;"value3"; (最后一个字段值括在引号和尾随分隔符中)
但这会破坏导入: ...;value2;"value 3" (最后一个字段值用引号括起来,没有尾随分隔符)

我花了一些时间来解决这个问题;希望分享这个可以节省其他人的时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-19
    • 2022-01-23
    • 2020-11-26
    • 1970-01-01
    • 2013-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多