Korjaa "a foreign key constraint fails" SQL-dumpia tuotaessa

Tuonti pysähtyy puolessa välissä virheeseen Cannot add or update a child row: a foreign key constraint fails. Data on kunnossa — INSERT-lauseiden järjestys on väärä. Tässä syy ja kolme tapaa korjata se.

Viet tietokannan, yrität ladata sen tyhjään instanssiin, ja MySQL antaa virheen:

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

Tai PostgreSQL:ssä:

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

Miksi näin käy

Viiteavain sanoo: “jokaisen orders.user_id-arvon täytyy osoittaa olemassa olevaan users.id-riviin.” Kun dumppi lisää orders-taulun ennen users-taulua, viitattua yläriviä ei vielä ole olemassa, ja tietokanta hylkää rivin.

Useimmat dumppaustyökalut kirjoittavat taulut aakkosjärjestyksessä tai luontijärjestyksessä — eivät viiteavainten riippuvuusjärjestyksessä. Niinpä orders (lapsi) päätyy usein ennen users-taulua (vanhempi), ja tuonti kaatuu.

Korjaus 1: Järjestä INSERTit riippuvuuksien mukaan (oikea korjaus)

Siisti ratkaisu on lisätä jokainen ylätaulu ennen sen lapsia. Se tarkoittaa viiteavainten ratkaisemista riippuvuusgraafiksi ja taulujen lataamista topologisessa järjestyksessä: users → orders → order_items.

Tämän tekeminen käsin monen gigatavun tiedostossa on tuskallista — sinun on jäljitettävä jokainen FOREIGN KEY CREATE TABLE- ja ALTER TABLE -lauseista ja leikattava/liitettävä valtavia INSERT-lohkoja oikeaan järjestykseen.

Korjaus 2: Poista viiteavaintarkistukset käytöstä tuonnin ajaksi

Täydelliselle, jo valmiiksi eheälle dumpille voit turvallisesti ohittaa validoinnin latauksen aikana. MySQL:ssä kääri tiedosto:

-- MySQL
SET FOREIGN_KEY_CHECKS = 0;
-- ... kaikki INSERT-lauseesi ...
SET FOREIGN_KEY_CHECKS = 1;

PostgreSQL:ssä lykkää rajoitteita transaktion sisällä:

-- PostgreSQL
BEGIN;
SET CONSTRAINTS ALL DEFERRED;
-- ... kaikki INSERT-lauseesi ...
COMMIT;

Ota tarkistukset takaisin käyttöön jälkeenpäin, jotta tulevat kirjoitukset pysyvät validoituina. Tämä toimii, mutta se vain peittää järjestysongelman — jos dumppi on osittainen, voit silti päätyä orpoihin riveihin.

Korjaus 3: Tee molemmat automaattisesti DumpCleanerilla

DumpCleaner lukee dumpin, poimii jokaisen viiteavaimen CREATE TABLE- ja ALTER TABLE -lauseista, rakentaa riippuvuusgraafin ja vie puhtaan tiedoston, joka tuodaan ilman ongelmia:

  1. Vedä .sql-dumppisi DumpCleaneriin (MySQL, MariaDB, PostgreSQL, SQLite tai MS SQL).
  2. Valitse INSERT-järjestys → Riippuvuuksien mukaan (viiteavaintietoinen). Vanhemmat sijoitetaan lasten eteen automaattisesti topologisella lajittelulla.
  3. Halutessasi rastita Poista viiteavaintarkistukset käytöstä — se kääri tulosteen tietokannallesi oikealla lauseella.
  4. Vie. Tuo uusi tiedosto — rajoitevirhe on poissa.

Se jopa tunnistaa kehämäiset viiteavaimet ja varoittaa sinua sen sijaan, että tuottaisi mahdottoman järjestyksen.

Ei enää manuaalista INSERT-kirurgiaa

DumpCleaner järjestää insertit viiteavainriippuvuuksien mukaan minkä tahansa kokoisissa tiedostoissa — striimaten, vakiomuistilla. Natiivi macOS- & iPadOS-sovellus, kertaosto.

Lataa App Storesta

Usein kysytyt kysymykset

Miksi “a foreign key constraint fails” tapahtuu tuonnissa?

Lapsirivi viittaa ylätauluriviin, jota ei ole vielä lisätty, koska dumppi järjestää INSERTit aakkosjärjestyksessä tai luontiajan mukaan viiteavainriippuvuuden sijaan.

Onko turvallista poistaa viiteavaintarkistukset käytöstä tuonnin aikana?

Kyllä, täydelliselle ja eheälle dumpille. Ohitat vain sellaisen datan validoinnin, joka oli jo lähdetietokannassa validia. Ota tarkistukset takaisin käyttöön jälkeenpäin.

Miten järjestän INSERTit uudelleen muokkaamatta tiedostoa käsin?

DumpCleaner tunnistaa viiteavaimet, rakentaa riippuvuusgraafin ja vie INSERTit topologisessa järjestyksessä — niin vanhemmat latautuvat aina ennen lapsia.

Toimiiko tämä myös PostgreSQL:llä?

Kyllä. DumpCleaner tukee pg_dump-tulostetta ja voi tuottaa SET CONSTRAINTS ALL DEFERRED -lauseen sekä riippuvuusjärjestettyjä insertejä.

Tuo dumpit ilman viiteavainpäänvaivaa

Vedä, järjestä riippuvuuksien mukaan, vie. DumpCleaner hoitaa viiteavaimet, joten tuontisi vain toimii.

Lataa App Storesta