Поправка на „a foreign key constraint fails“ при импорт на SQL дъмп

Импортът ви спира по средата с Cannot add or update a child row: a foreign key constraint fails. Данните са наред — редът на INSERT заявките е грешен. Ето защо се случва и три начина да го поправите.

Експортирате база данни, опитвате се да я заредите в нов инстанс и MySQL връща:

ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint fails (`app`.`orders`, CONSTRAINT `orders_user_id_fk` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`))

Или, при PostgreSQL:

ERROR: insert or update on table "orders" violates foreign key constraint "orders_user_id_fkey"
DETAIL: Key (user_id)=(42) is not present in table "users".

Защо се случва това

Външен ключ казва „всеки orders.user_id трябва да сочи към съществуващ users.id.“ Когато дъмпът вмъква orders преди users, реферираният родителски ред още не съществува и базата данни отхвърля реда.

Повечето инструменти за дъмп записват таблиците по азбучен ред или в реда на създаване — а не в реда на зависимостите на външните ключове. Затова orders (дъщерна) често се озовава преди users (родителска) и импортът се проваля.

Решение 1: Пренаредете INSERT заявките по зависимости (правилната поправка)

Чистото решение е да вмъкнете всяка родителска таблица преди нейните дъщерни. Това означава да преобразувате външните ключове в граф на зависимостите и да заредите таблиците в топологичен ред: users → orders → order_items.

Правенето на това на ръка в многогигабайтов файл е мъчение — трябва да проследите всеки FOREIGN KEY из CREATE TABLE и ALTER TABLE заявките и да изрежете/поставите огромни INSERT блокове в правилната последователност.

Решение 2: Изключете проверките на външни ключове по време на импорта

За пълен, вече съгласуван дъмп можете безопасно да пропуснете валидацията по време на зареждането. При MySQL обвийте файла:

-- MySQL
SET FOREIGN_KEY_CHECKS = 0;
-- ... всички ваши INSERT заявки ...
SET FOREIGN_KEY_CHECKS = 1;

При PostgreSQL отложете ограниченията в рамките на транзакция:

-- PostgreSQL
BEGIN;
SET CONSTRAINTS ALL DEFERRED;
-- ... всички ваши INSERT заявки ...
COMMIT;

Включете отново проверките след това, за да останат бъдещите записи валидирани. Това работи, но само маскира проблема с подредбата — ако дъмпът е частичен, все още можете да се озовете с осиротели редове.

Решение 3: Направете и двете автоматично с DumpCleaner

DumpCleaner прочита дъмпа, извлича всеки външен ключ от CREATE TABLE и ALTER TABLE, изгражда графа на зависимостите и експортира чист файл, който просто се импортира:

  1. Плъзнете вашия .sql дъмп в DumpCleaner (MySQL, MariaDB, PostgreSQL, SQLite или MS SQL).
  2. Изберете Ред на INSERT → По зависимости (съобразено с външни ключове). Родителите се поставят преди дъщерните автоматично чрез топологично сортиране.
  3. По желание отметнете Изключване на проверките за външни ключове — обвива изхода с правилната заявка за вашата база данни.
  4. Експортирайте. Импортирайте новия файл — грешката с ограничението изчезна.

Дори засича кръгови външни ключове и ви предупреждава, вместо да произведе невъзможен ред.

Край на ръчната хирургия по INSERT заявките

DumpCleaner пренарежда вмъкванията по зависимости на външните ключове върху файлове с всякакъв размер — поточно, с постоянна памет. Нативно приложение за macOS и iPadOS, еднократна покупка.

Изтегляне от App Store

Често задавани въпроси

Защо се появява „a foreign key constraint fails“ при импорт?

Дъщерен ред реферира родителски ред, който още не е вмъкнат, защото дъмпът подрежда INSERT заявките по азбучен ред или по време на създаване, а не по зависимост на външните ключове.

Безопасно ли е да изключа проверките за външни ключове по време на импорт?

Да, за пълен и съгласуван дъмп. Пропускате само валидацията на данни, които вече са били валидни в изходната база данни. Включете отново проверките след това.

Как да пренаредя INSERT заявките, без да редактирам файла на ръка?

DumpCleaner засича външните ключове, изгражда граф на зависимостите и експортира INSERT заявките в топологичен ред — така че родителите винаги се зареждат преди дъщерните.

Работи ли това и за PostgreSQL?

Да. DumpCleaner поддържа изхода на pg_dump и може да генерира SET CONSTRAINTS ALL DEFERRED, както и вмъквания, подредени по зависимости.

Импортирайте дъмпове без главоболията с външните ключове

Плъзнете, пренаредете по зависимости, експортирайте. DumpCleaner се грижи за външните ключове, така че импортът ви просто работи.

Изтегляне от App Store