MySQL дубликаты с загрузкой данных INFILE

При использовании LOAD DATA INFILE, есть ли способ пометить дублирующую строку или сбросить любые / все дубликаты в отдельную таблицу?

2 ответа

Решение

Из документации ЗАГРУЗИТЬ ДАТУ INFILE:

Ключевые слова REPLACE и IGNORE управляют обработкой входных строк, которые дублируют существующие строки с уникальными значениями ключа:

  • Если вы укажете REPLACE, входные строки заменят существующие. Другими словами, строки, которые имеют то же значение для первичного ключа или уникального индекса, что и существующая строка. Смотрите Раздел 12.2.7, "ЗАМЕНИТЕ Синтаксис".
  • Если вы укажете IGNORE, входные строки, дублирующие существующую строку с уникальным значением ключа, будут пропущены. Если вы не укажете ни один из параметров, поведение зависит от того, указано ли ключевое слово LOCAL. Без LOCAL возникает ошибка, когда обнаруживается повторяющееся значение ключа, а остальная часть текстового файла игнорируется. С LOCAL поведение по умолчанию такое же, как если бы был указан IGNORE; это связано с тем, что сервер не может остановить передачу файла в середине операции.

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

Похоже, что на самом деле есть что-то, что вы можете сделать, когда дело доходит до дублирования строк для вызовов LOAD DATA. Однако подход, который я нашел, не идеален: он действует скорее как журнал для всех удалений в таблице, а не только для вызовов LOAD DATA. Вот мой подход:

Настольный тест:

CREATE TABLE test (
    id INTEGER PRIMARY KEY,
    text VARCHAR(255) DEFAULT NULL
);

Таблица test_log:

CREATE TABLE test_log (
    id INTEGER, -- not primary key, we want to accept duplicate rows
    text VARCHAR(255) DEFAULT NULL,
    time TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Триггер del_chk:

delimiter //
drop trigger if exists del_chk;
CREATE TRIGGER del_chk AFTER DELETE ON test
FOR EACH ROW
BEGIN
    INSERT INTO test_log(id,text) values(OLD.id,OLD.text);
END;//
delimiter ;

Тестовый импорт (/home/user/test.csv):

1,asdf
2,jkl
3,qwer
1,tyui
1,zxcv
2,bnm

Запрос:

LOAD DATA INFILE '/home/ken/test.csv'
REPLACE INTO TABLE test 
FIELDS 
    TERMINATED BY ','
LINES
    TERMINATED BY '\n' (id,text);

Выполнение вышеуказанного запроса приведет к 1,asdf, 1,tyui, а также 2,jkl добавляется в таблицу журнала. Основываясь на отметке времени, можно связать строки с определенным LOAD DATA заявление.

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