Предотвратить загрузку DATA INFILE от двойных двойных кавычек
У меня есть данные 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?$)", '""');
как раз перед последней строкой в функции, и это, кажется, работает хорошо. Поскольку я новичок в регулярных выражениях, это, вероятно, можно улучшить.
1 ответ
Основная проблема заключается в том, что входные данные составляют недопустимый синтаксис CSV, как указано в параграфе 7 RFC-4180:
Если двойные кавычки используются для включения полей, то двойная кавычка, появляющаяся внутри поля, должна быть экранирована, если перед ней стоит еще одна двойная кавычка.
Но в вашем скрипте PowerShell вы можете попытаться исправить эту проблему с помощью дополнительной строки, используя метод replace для $ text, как только вы получите его значение:
$text = $text.Replace('"";', '""";')
Этого должно быть достаточно, так как загрузчик будет хорошо справляться с неэкранированными двойными кавычками, если они появятся в других местах данных, как указано на mysql.com (мой основной момент):
Если поле начинается с
ENCLOSED BY
символ, экземпляры этого символа распознаются как завершающие значение поля, только если за ними следует поле или строкаTERMINATED BY
последовательность.
Конечно, если в плохо отформатированном CSV есть данные, содержащие ";
, тогда у вас все еще есть проблема. Но очень трудно определить, завершает ли такой случай данные или их следует рассматривать как часть данных, даже для людей:-)
Еще одна вещь, на которую стоит обратить внимание, как на mysql.com:
Если входные значения не обязательно заключены в кавычки, используйте
OPTIONALLY
передENCLOSED
По ключевым словам.
Кроме того: импорт CSV-файлов в MySQL со значениями, заключенными в кавычки, работает нормально при использовании опции ENCLOSED BY. ЕСЛИ МЕДИЦИНСКОЕ поле не является последним полем в строке, И вы использовали Excel для создания CSV-файла. В Excel пропускается разделитель полей после последнего поля в строке. MySQL не возражает... если последнее поле не заключено в кавычки. Затем импорт заканчивается на этой строке.
Примеры:
Это прекрасно работает: ...; значение2; значение3 (без конечного разделителя)
Это также отлично работает...;"значение 2"; значение3 (значение заключено в кавычки)
Это также отлично работает...; значение 2;"значение3"; (последнее значение поля заключено в кавычки и конечный разделитель)
Но это нарушает импорт: ...;value2;"value 3" (последнее значение поля заключено в кавычки и без конечного разделителя)
Мне понадобилось время, чтобы понять это; надеюсь, что разделение этого спасет кого-то еще в это время.