Копирование из одной таблицы в другую, как обеспечить проверку внешнего ключа для всего набора данных, но не для отдельных строк?

0

Я использую MySQL. Предположим, что у меня есть hierarchy таблицы с двумя столбцами: id, parent_id.

parent_id ссылается на id другой строки той же таблицы, поэтому у меня есть внешний ключ.

В таблице hierarchy содержатся некоторые данные, но теперь они не актуальны.

У меня также есть вторая таблица с именем new_hierarchy_entries которая имеет одинаковые столбцы, но нет ограничений внешнего ключа.

new_hierarchy_entries содержит:

id    parent_id
2     1
1     null

Теперь я хочу скопировать все строки из new_hierarchy_entries в hierarchy. Когда я бегу наивно:

INSERT INTO hierarchy SELECT * FROM new_hierarchy_entries

Я получаю сообщение об ошибке: Не удается добавить или обновить дочернюю строку: ограничение внешнего ключа завершается с ошибкой (my_db. hierarchy, CONSTRAINT hierarchy_ibfk_2 ИНОСТРАННЫЙ КЛЮЧ (parent_id) hierarchy ССЫЛКИ (id))

Конечно, если строки вставлены один за другим, первая строка (id = 2, parent = 1) не может быть вставлена, потому что в hierarchy таблицы нет строки с id = 1.

С другой стороны, если бы все строки были добавлены сразу, то ограничения были бы выполнены. Итак, как я могу скопировать строки таким образом, что я уверен, что ограничения выполняются после копирования, но они могут не выполняться при копировании?

Сортировка строк new_hierarchy_entries по id не поможет. Я не могу предположить, что parent_id < id в той же строке.

Сортировка строк new_hierarchy_entries по иерархии (используя терминологию дерева, дайте мне сначала, потом их родители и т.д.), Но я не уверен, как это сделать в запросе MySQL.

Я играл с идеей временно отключить FOREIGN_KEY_CHECKS. Но потом я мог вставить непоследовательные данные, и я бы не узнал. Превращение FOREIGN_KEY_CHECKS не делает проверку базы данных согласованностью всех данных. В любом случае, потребуется слишком много ресурсов.

Теги:

1 ответ

0

Это сложно. Я не знаю, как заставить MySQL повторно проверять ссылки на внешние ключи после включения FOREIGN_KEY_CHECKS.

Вы можете проверить себя на сиротские строки, а если есть, откиньтесь назад.

BEGIN;

SET SESSION FOREIGN_KEY_CHECKS=0;
INSERT INTO hierarchy SELECT * FROM new_hierarchy_entries;
SET SESSION FOREIGN_KEY_CHECKS=1;

SELECT COUNT(*) FROM hierarchy AS c 
LEFT OUTER JOIN hierarchy AS p ON p.id=c.parent_id
WHERE p.id IS NULL;
-- if count == 0 then...
COMMIT;

-- otherwise ROLLBACK and investigate the bad data

Еще одна возможность - использовать INSERT с опцией IGNORE, которая пропустит неудачные строки. Затем повторите ту же инструкцию в цикле, если вы видите, что "затронутые строки" больше 0.

INSERT IGNORE INTO hierarchy SELECT * FROM new_hierarchy_entries;
INSERT IGNORE INTO hierarchy SELECT * FROM new_hierarchy_entries;
INSERT IGNORE INTO hierarchy SELECT * FROM new_hierarchy_entries;
...

Ещё вопросы

Сообщество Overcoder
Наверх
Меню