Paranda „a foreign key constraint fails" SQL-tõmmise importimisel

Sinu import peatub poole peal veateatega Cannot add or update a child row: a foreign key constraint fails. Andmed on korras — vale on INSERT-lausete järjekord. Siin on selle põhjus ja kolm viisi, kuidas seda parandada.

Ekspordid andmebaasi, proovid selle värskesse eksemplari laadida ja MySQL viskab vea:

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`))

Või PostgreSQL-is:

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".

Miks see juhtub

Välisvõti ütleb, et „iga orders.user_id peab osutama olemasolevale users.id-le". Kui tõmmis lisab orders enne users-i, siis viidatud vanemarida veel ei eksisteeri ja andmebaas lükkab rea tagasi.

Enamik tõmmisetööriistu kirjutab tabelid tähestikulises järjekorras või loomise järjekorras — mitte välisvõtme sõltuvuse järjekorras. Seega satub orders (laps) sageli users-i (vanem) ette ja import katkeb.

Lahendus 1: järjesta INSERT-id sõltuvuse järgi (õige lahendus)

Puhas lahendus on lisada iga vanemtabel enne selle lapsi. See tähendab välisvõtmete lahendamist sõltuvusgraafiks ja tabelite laadimist topoloogilises järjekorras: users → orders → order_items.

Seda käsitsi teha mitmegigabaidises failis on valus — pead jälgima iga FOREIGN KEY-d läbi CREATE TABLE- ja ALTER TABLE-lausete ning lõikama/kleepima suuri INSERT-plokke õiges järjekorras.

Lahendus 2: keela välisvõtmete kontrollid importimise ajaks

Täieliku ja juba järjepideva tõmmise puhul võid laadimise ajal valideerimise ohutult vahele jätta. MySQL-is mähi fail sisse:

-- MySQL
SET FOREIGN_KEY_CHECKS = 0;
-- ... kõik sinu INSERT-laused ...
SET FOREIGN_KEY_CHECKS = 1;

PostgreSQL-is lükka piirangud tehingu sees edasi:

-- PostgreSQL
BEGIN;
SET CONSTRAINTS ALL DEFERRED;
-- ... kõik sinu INSERT-laused ...
COMMIT;

Luba kontrollid pärast uuesti, et tulevased kirjutamised jääksid valideerituks. See toimib, kuid varjab vaid järjestamise probleemi — kui tõmmis on osaline, võivad sul ikkagi tekkida orvuks jäänud read.

Lahendus 3: tee mõlemad automaatselt DumpCleaneriga

DumpCleaner loeb tõmmise, eraldab iga välisvõtme CREATE TABLE- ja ALTER TABLE-lausetest, ehitab sõltuvusgraafi ja ekspordib puhta faili, mis lihtsalt imporditakse:

  1. Lohista oma .sql-tõmmis DumpCleanerisse (MySQL, MariaDB, PostgreSQL, SQLite või MS SQL).
  2. Vali INSERT-järjekord → Sõltuvuste järgi (välisvõtme teadlik). Vanemad paigutatakse laste ette automaatselt topoloogilise sortimisega.
  3. Soovi korral märgi Keela välisvõtmete kontrollid — see mähib väljundi sinu andmebaasi jaoks õige lausega.
  4. Ekspordi. Impordi uus fail — piirangu viga on kadunud.

See tuvastab isegi tsüklilised välisvõtmed ja hoiatab sind, selle asemel et toota võimatut järjekorda.

Enam ei mingit käsitsi INSERT-kirurgiat

DumpCleaner järjestab INSERT-id välisvõtme sõltuvuse järgi mis tahes suurusega failides — voogedastades, konstantse mäluga. Natiivne macOS-i ja iPadOS-i rakendus, ühekordne ost.

Laadi alla App Store'ist

Korduma kippuvad küsimused

Miks tekib importimisel „a foreign key constraint fails"?

Lapsrida viitab vanemreale, mida pole veel lisatud, sest tõmmis järjestab INSERT-id tähestikuliselt või loomise aja järgi, mitte välisvõtme sõltuvuse järgi.

Kas välisvõtmete kontrollide keelamine importimise ajaks on ohutu?

Jah, täieliku ja järjepideva tõmmise puhul. Sa jätad vahele vaid selliste andmete valideerimise, mis olid lähteandmebaasis juba kehtivad. Luba kontrollid pärast uuesti.

Kuidas järjestada INSERT-id ilma faili käsitsi muutmata?

DumpCleaner tuvastab välisvõtmed, ehitab sõltuvusgraafi ja ekspordib INSERT-id topoloogilises järjekorras — nii et vanemad laaditakse alati enne lapsi.

Kas see toimib ka PostgreSQL-i puhul?

Jah. DumpCleaner toetab pg_dumpi väljundit ja oskab väljastada nii SET CONSTRAINTS ALL DEFERRED kui ka sõltuvuse järgi järjestatud INSERT-id.

Impordi tõmmiseid ilma välisvõtme peavaluta

Lohista, järjesta sõltuvuste järgi, ekspordi. DumpCleaner tegeleb välisvõtmetega, nii et sinu import lihtsalt toimib.

Laadi alla App Store'ist