sql >> Database >  >> RDS >> Mysql

MySQL Tabellen maken met buitenlandse sleutels die errno geven:150

Ik had hetzelfde probleem met ALTER TABLE ADD FOREIGN KEY .

Na een uur ontdekte ik dat aan deze voorwaarden moet worden voldaan om fout 150 niet te krijgen:

  1. De bovenliggende tabel moet bestaan ​​voordat u een refererende sleutel definieert om ernaar te verwijzen. U moet de tabellen in de juiste volgorde definiëren:eerst de bovenliggende tabel, dan de onderliggende tabel. Als beide tabellen naar elkaar verwijzen, moet u één tabel maken zonder FK-beperkingen, vervolgens de tweede tabel maken en vervolgens de FK-beperking aan de eerste tabel toevoegen met ALTER TABLE .

  2. De twee tabellen moeten beide externe-sleutelbeperkingen ondersteunen, d.w.z. ENGINE=InnoDB . Andere opslag-engines negeren de definities van buitenlandse sleutels stilletjes, dus ze geven geen fout of waarschuwing terug, maar de FK-beperking wordt niet opgeslagen.

  3. De kolommen waarnaar in de bovenliggende tabel wordt verwezen, moeten de meest linkse kolommen van een sleutel zijn. Het beste als de sleutel in de bovenliggende sleutel PRIMARY KEY is of UNIQUE KEY .

  4. De FK-definitie moet verwijzen naar de PK-kolom(men) in dezelfde volgorde als de PK-definitie. Als de FK REFERENCES Parent(a,b,c) dan mag de PK van de ouder niet op volgorde van kolommen worden gedefinieerd (a,c,b) .

  5. De PK-kolom(men) in de Bovenliggende tabel moeten hetzelfde gegevenstype hebben als de FK-kolom(men) in de Onderliggende tabel. Als een PK-kolom in de bovenliggende tabel bijvoorbeeld UNSIGNED . is , zorg ervoor dat u UNSIGNED definieert voor de corresponderende kolom in het veld Onderliggende tabel.

    Uitzondering:de lengte van de snaren kan verschillen. Bijvoorbeeld VARCHAR(10) kan verwijzen naar VARCHAR(20) of omgekeerd.

  6. Alle FK-kolom(men) van het tekenreekstype moeten dezelfde tekenset en sortering hebben als de corresponderende PK-kolom(men).

  7. Als er al gegevens in de onderliggende tabel staan, moet elke waarde in de FK-kolom(men) overeenkomen met een waarde in de PK-kolom(men) van de bovenliggende tabel. Controleer dit met een vraag als:

    SELECT COUNT(*) FROM Child LEFT OUTER JOIN Parent ON Child.FK = Parent.PK 
    WHERE Parent.PK IS NULL;
    

    Dit moet nul (0) niet-overeenkomende waarden retourneren. Het is duidelijk dat deze query een generiek voorbeeld is; u moet uw tabelnamen en kolomnamen vervangen.

  8. Noch de bovenliggende tabel, noch de onderliggende tabel kan een TEMPORARY zijn tafel.

  9. Noch de bovenliggende tabel, noch de onderliggende tabel kan een PARTITIONED . zijn tafel.

  10. Als u een FK declareert met de ON DELETE SET NULL optie, dan moeten de FK-kolom(men) nullable zijn.

  11. Als u een beperkingsnaam voor een externe sleutel declareert, moet de beperkingsnaam uniek zijn in het hele schema, niet alleen in de tabel waarin de beperking is gedefinieerd. Twee tabellen hebben mogelijk geen eigen beperking met dezelfde naam.

  12. Als er andere FK's in andere tabellen zijn die naar hetzelfde veld wijzen waarvoor u de nieuwe FK probeert te maken, en deze zijn niet correct gevormd (d.w.z. een andere sortering), moeten ze eerst consistent worden gemaakt. Dit kan het gevolg zijn van eerdere wijzigingen waarbij SET FOREIGN_KEY_CHECKS = 0; werd gebruikt met een per abuis gedefinieerde inconsistente relatie. Zie het antwoord van @andrewdotn hieronder voor instructies om deze probleem-FK's te identificeren.

Ik hoop dat dit helpt.



  1. Hoe SHOW COLLATION werkt in MariaDB

  2. Verwijder zeer grote databases

  3. Wat is de standaardnaam van de beperking in SQL Server?

  4. Toegang tot de webservice vanuit de opgeslagen procedure van Oracle