Предотвратить загрузку 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" (последнее значение поля заключено в кавычки и без конечного разделителя)

Мне понадобилось время, чтобы понять это; надеюсь, что разделение этого спасет кого-то еще в это время.

Другие вопросы по тегам