null

MySQL: Ошибка импорта из CSV файла

На днях передо мной встала довольно рутинная задача: заблокировать аккаунты пользователей по списку. Cписок email в csv файле. Доступ в базу есть, нужно у соответствующих учёток обновить поле is_active на false, только и всего.

Выполнить задачу я решил путём импорта email-ов во временную таблицу и последующий апдейт по условию:

-- Временная таблица
CREATE TEMPORARY TABLE tmp_emails (email varchar(254));

-- Импорт email из файла
LOAD DATA INFILE '/tmp/email.csv' INTO TABLE tmp_emails
FIELDS TERMINATED BY ',' ENCLOSED BY '"'
LINES TERMINATED BY '\n'
IGNORE 1 ROWS -- заголовок
;

-- Проверка кол-ва совпадений
SELECT COUNT(*) AS found FROM users u JOIN tmp_emails e ON u.email = e.email;

-- Начало транзакции
BEGIN;

-- Обновление записей
UPDATE users SET is_active = false
WHERE email IN (SELECT email FROM tmp_emails);

-- Фиксация транзакции или откат
-- COMMIT;
-- ROLLBACK;

Однако, на этапе проверки, я получил 0 совпадений. Таким образом обновить ничего не получится. Я решил убедиться, что временная таблица не пуста и увидел там примерно такое... кривое, косое, непонятное:

+------------------------+
| email                  |
+------------------------+
     |a@example.com
 |petrov_ab@example.com
+------------------------+

Почему же таблицу рас******сило? Откуда взялась вертикальная черта и куда потерялась часть символов в email???

Поломав голову, я пришёл к выводу, что получил текстовый файл с переносами строк в формате dos, а не unix. Т.е. перенос строки в файле состоит из двух символов: \r\n, а для разбора файла я указал лишь один \n. Получилось, что каждый email во временной таблице имеет символ \r на конце. Поэтому вывод в консоль выглядит так странно и поэтому JOIN таблиц по email выдало мне 0 совпадений.

Варианты исправления очевидны:

  • Меняем формат исходного файла, например в vim это можно сделать так: :wq ++ff=unix (меняем формат, сохраняем и выходим).
  • Во время импорта указать LINES TERMINATED BY '\r\n'

Естественно, нужно применить только один из вариантов. После этого email импортировались корректно, а вывод из таблицы выглядит как положено:

+-----------------------+
| email                 |
+-----------------------+
| petya@example.com     |
| petrov_ab@example.com |
+-----------------------+

Теперь проблем с апдейтом не возникло ;)

Next