MySQL загружает значения NULL из данных CSV


167

У меня есть файл, который может содержать от 3 до 4 столбцов числовых значений, разделенных запятой. Пустые поля определяются за исключением того, что они находятся в конце строки:

1,2,3,4,5
1,2,3,,5
1,2,3

Следующая таблица была создана в MySQL:

+ ------- + -------- + ------ + ----- + --------- + ------- +
| Поле | Тип | Null | Ключ | По умолчанию | Extra |
+ ------- + -------- + ------ + ----- + --------- + ------- +
| один | int (1) | ДА | | NULL | |
| два | int (1) | ДА | | NULL | |
| три | int (1) | ДА | | NULL | |
| четыре | int (1) | ДА | | NULL | |
| пять | int (1) | ДА | | NULL | |
+ ------- + -------- + ------ + ----- + --------- + ------- +

Я пытаюсь загрузить данные с помощью команды MySQL LOAD:

LOAD DATA INFILE '/tmp/testdata.txt' INTO TABLE moo FIELDS 
TERMINATED BY "," LINES TERMINATED BY "\n";

Полученная таблица:

+ ------ + ------ + ------- + ------ + ------ +
| один | два | три | четыре | пять |
+ ------ + ------ + ------- + ------ + ------ +
| 1 | 2 | 3 | 4 | 5 |
| 1 | 2 | 3 | 0 | 5 |
| 1 | 2 | 3 | NULL | NULL |
+ ------ + ------ + ------- + ------ + ------ +

Проблема заключается в том, что когда поле в необработанных данных пусто и не определено, MySQL по какой-то причине не использует значение по умолчанию для столбцов (которое равно NULL) и использует ноль. NULL используется правильно, когда поле полностью отсутствует.

К сожалению, я должен уметь различать NULL и 0 на этом этапе, поэтому любая помощь будет оценена.

Спасибо С.

редактировать

Вывод ШОУ ПРЕДУПРЕЖДЕНИЙ:

+ --------- + ------ + -------------------------------- ------------------------ +
| Уровень | Код | Сообщение |
+ --------- + ------ + -------------------------------- ------------------------ +
| Предупреждение 1366 | Неверное целочисленное значение: '' для столбца 'четыре' в строке 2 |
| Предупреждение 1261 | Строка 3 не содержит данных для всех столбцов |
| Предупреждение 1261 | Строка 3 не содержит данных для всех столбцов |
+ --------- + ------ + -------------------------------- ------------------------ +

При таких изменениях схемы данных я бы использовал d6tstack, который выравнивает все столбцы перед запуском LOAD DATA. Смотрите раздел примеров d6tstack SQL об изменениях схемы данных.
сеньорнман

Ответы:


193

Это будет делать то, что вы хотите. Он считывает четвертое поле в локальную переменную, а затем устанавливает фактическое значение поля в NULL, если локальная переменная заканчивается пустой строкой:

LOAD DATA INFILE '/tmp/testdata.txt'
INTO TABLE moo
FIELDS TERMINATED BY ","
LINES TERMINATED BY "\n"
(one, two, three, @vfour, five)
SET four = NULLIF(@vfour,'')
;

Если они все, возможно, пустые, то вы бы прочитали их все в переменные и имели бы несколько операторов SET, например:

LOAD DATA INFILE '/tmp/testdata.txt'
INTO TABLE moo
FIELDS TERMINATED BY ","
LINES TERMINATED BY "\n"
(@vone, @vtwo, @vthree, @vfour, @vfive)
SET
one = NULLIF(@vone,''),
two = NULLIF(@vtwo,''),
three = NULLIF(@vthree,''),
four = NULLIF(@vfour,'')
;

Теоретически, я полагаю - но все это в памяти и содержит только небольшие объемы данных в строке, поэтому я представляю, что это будет бесконечно мало; но вы должны проверить это, если вы думаете, что это может быть проблемой.
Дункан Лок

4
Мне очень нравится этот ответ. Пользователи могут видеть пустые строки, ''когда они загружают CSV (используя IFNULL(Col,'')в SELECT INTO OUTFILEзапросе) для Excel, но затем загрузки принимают их как ноль против необходимости иметь дело \Nв CSV. Спасибо!
Крисан

9
для дат я использовал 'NULLIF (STR_TO_DATE (@ date1, "% d /% m /% Y"), "0000-00-00")'
Хоакин Л. Роблес

1
У меня есть CSV-файл, который содержит нули, 0которые должны быть преобразованы в NULL(поскольку невозможно получить нулевое значение для рассматриваемых данных), а также пустые строки. Как убедиться, что и нули, и пустые строки преобразованы в NULL?
Поль Ружье,

Если нулевые значения и пустые строки в отдельных колонках, то вобще выше для пустых строк, и что - то вроде этого для нулей: nullif(@vone, 0).
Дункан Лок

136

Руководство MySQL гласит:

При чтении данных с помощью LOAD DATA INFILE пустые или отсутствующие столбцы обновляются с помощью ''. Если вы хотите получить значение NULL в столбце, вы должны использовать \ N в файле данных. Буквальное слово «NULL» также может использоваться при некоторых обстоятельствах.

Таким образом, вам нужно заменить заготовки на \ N, как это:

1,2,3,4,5
1,2,3,\N,5
1,2,3

3
Спасибо за совет - я скептически отношусь к редактированию необработанных исходных данных, но если это единственный способ обойти это, я попробую.
Спирос

7
Я понимаю ваш скептицизм, никто не любит редактировать необработанные данные, просто он не чувствует себя хорошо. Однако, если вы задумаетесь об этом в течение минуты, должен быть способ различать NULL и пустую строку. Если пустые записи будут переведены в NULL, вам понадобится специальная последовательность для пустой строки. Было бы хорошо, если бы у MySQL был способ объяснить, как обрабатывать пустые записи, например, LOAD DATA INFILE '/tmp/testdata.txt' INTO TABLE moo TREAT BLANKS AS NULL ...
Янси

2
Хорошо, но если у вас есть Fields enclosed by: "то , что "\N"из"name",\N,"stuff"
Джонатон

3
Я могу убедиться, что по крайней мере для «phpMyAdmin 3.5.5» ни один стиль \Nне принимается как обозначающий NULL. Вместо этого используйте NULL, как в этом примере:"name","age",NULL,"other","stuff"
Джонатон

1
У нас есть MySQL 5.5.46-0 + deb8u1. Я пробовал оба NULL и \ N, и только \ N работал для нас.
Raphael75

6

Поведение отличается в зависимости от конфигурации базы данных. В строгом режиме это выдаст ошибку, иначе предупреждение. Следующий запрос может быть использован для определения конфигурации базы данных.

mysql> show variables like 'sql_mode';

Спасибо! Я ломал голову, пытаясь понять, почему импорт CSV с пустыми столбцами, которые я успешно импортировал на рабочий сервер вчера, не работал на моей новой локальной установке - это был ответ в моем случае!
Эмма Берроуз

3

Предварительно обработайте введенный CSV, чтобы заменить пустые записи на \ N.

Попытка в регулярном выражении: s / ,, /, \ n, / g и s /, $ /, \ N / g

Удачи.


1
Это регулярное выражение частично работает, оно не решает последовательные пустые записи, например ,,,, будет, \ n ,, \ n, должно быть пригодно для использования, если вы запустите его дважды
ievgen

1
Подведу итоги ответа и предыдущего комментария. Следующее сработало для меня, в следующем порядке: sed -i 's / ,, /, \ N / g' $ file, sed -i 's / ,, /, / g' $ file, sed -i 's / \ N, $ / \ N / g '$ file,
Омар Хазамов

Я хотел бы сделать это, но мне не ясно, как вы используете это регулярное выражение. Если вы используете MySQL для запуска этого файла, это будет лучшим решением. Но вы не говорите, и я не хочу тратить кучу времени на поиски того, как сделать что-то, что может оказаться невозможным.
DonkeyKong

1

(variable1, @ variable2, ..) SET variable2 = nullif (@ variable2, '' или '') >> вы можете поставить любое условие


0

показать переменные

Show variables like "`secure_file_priv`";

Примечание. Храните CSV-файл в месте, указанном вышеупомянутой командой.

create table assessments (course_code varchar(5),batch_code varchar(7),id_assessment int, assessment_type varchar(10), date int , weight int);

Примечание: здесь dateстолбец ' ' имеет некоторые пустые значения в файле csv.

LOAD DATA INFILE 'C:/ProgramData/MySQL/MySQL Server 8.0/Uploads/assessments.csv' 
INTO TABLE assessments
FIELDS TERMINATED BY ',' 
OPTIONALLY ENCLOSED BY '' 
LINES TERMINATED BY '\n' 
IGNORE 1 ROWS 
(course_code,batch_code,id_assessment,assessment_type,@date,weight)
SET date = IF(@date = '', NULL, @date);
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.