MySQL завантажує значення NULL з даних CSV


167

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

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

Наступна таблиця створена в MySQL:

+ ------- + -------- + ------ + ----- + --------- + ------- +
| Поле | Тип | Нульовий | Ключові | За замовчуванням | Додаткові |
+ ------- + -------- + ------ + ----- + --------- + ------- +
| один | 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. Див. Розділ прикладів SQL d6tstack щодо змін схеми даних.
citynorman

Відповіді:


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. Дякую!
chrisan

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

1
У мене є файл csv, який містить нулі, 0які слід перетворити NULL(тому що для цих даних немає нульового значення), а також порожні рядки. Як переконатися, що і нулі, і порожні рядки перетворюються на NULL?
Пол Рудьо

Якщо нульові значення і порожні рядки в окремих колонках, то вобще вище для порожніх рядків, і що - щось на зразок цього для нулів: nullif(@vone, 0).
Замок Дункана

136

Посібник для MySQL говорить:

Під час зчитування даних із ЗАВАНТАЖЕННЯ ДАНИХ INFILE порожні або відсутні стовпці оновлюються символом ''. Якщо ви хочете значення NULL у стовпці, слід використовувати \ N у файлі даних. Буквальне слово "NULL" також може вживатися за певних обставин.

Тому вам потрібно замінити пробіли на \ N, як це:

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

3
Дякую за пораду - я скептично налаштовую вихідні вихідні дані, але якщо це єдиний спосіб, я спробую це випробувати.
Спірос

7
Я розумію ваш скептицизм, ніхто не любить редагувати необроблені дані, це просто не так. Однак якщо ви думаєте про це хвилину, повинен бути спосіб розрізнити NULL від порожнього рядка. Якщо порожні записи будуть переведені на NULL, вам знадобиться спеціальна послідовність для порожнього рядка. Було б добре, як розповісти MySQL, як поводитись із порожніми записами, щось на зразок ЗАВАНТАЖЕННЯ ДАНИХ INFILE '/tmp/testdata.txt' НА ТАБЛИЦЬ moo TREAT BLANKS AS NULL ...
Janci

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' $ файл, sed -i 's / ,, /, / g' $ файл, sed -i 's / \ N, $ / \ N / g '$ файл,
Омар Хазамов

Я хотів би це зробити, але мені не зрозуміло, як ви виконуєте цей регулярний вираз. Якщо ви використовуєте MySQL для запуску цього файлу, це було б найкращим рішенням. Але ти не кажеш, і я не хочу витрачати купу часу на гуглінг, як зробити щось, що може бути неможливим.
DonkeyKong


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.