sql >> Database >  >> RDS >> Mysql

Mysql en FK's probleem

De kolom(men) van de refererende sleutel moeten verwijzen naar kolom(men) die een voorvoegsel uiterst links van de primaire sleutel of een unieke sleutel in de bovenliggende tabel bevatten.

Met andere woorden, de volgende voorbeelden werken in InnoDB:

CREATE TABLE Foo ( a INT, b INT, c INT, PRIMARY KEY (a,b,c) );
CREATE TABLE Bar ( x INT, y INT );

ALTER TABLE Bar ADD FOREIGN KEY (x,y) REFERENCES Foo(b,c); -- WRONG

ALTER TABLE Bar ADD FOREIGN KEY (x,y) REFERENCES Foo(a,c); -- WRONG

ALTER TABLE Bar ADD FOREIGN KEY (x,y) REFERENCES Foo(a,b); -- RIGHT

ALTER TABLE Bar ADD FOREIGN KEY (x) REFERENCES Foo(b); -- WRONG

ALTER TABLE Bar ADD FOREIGN KEY (x) REFERENCES Foo(a); -- RIGHT

Er is een fout opgetreden omdat u het equivalent van (x) referenties Foo(b) probeert te doen.
Uw kolom codmenuitem is de tweede van drie kolommen in de primaire sleutel van de bovenliggende sleutel.

Het zou werken als smenuitememp.codemenuitem zouden verwijzen naar smenuitem.codmodulo , omdat die kolom de meest linkse kolom is in de primaire sleutel van de bovenliggende tabel.

Over uw vervolgvraag:

Houd rekening met de manier waarop buitenlandse sleutels werken. Telkens wanneer u een rij in de onderliggende tabel invoegt of bijwerkt, moet deze een rij opzoeken in de bovenliggende tabel om te controleren of de waarde bestaat in de kolom waarnaar wordt verwezen. Als de kolom niet is geïndexeerd, moet er een tabelscan worden uitgevoerd om deze zoekopdracht uit te voeren, en dat zou erg duur zijn, ervan uitgaande dat uw bovenliggende tabel groeit.

Als u een rij probeert op te zoeken op basis van de middelste kolom van een index met meerdere kolommen, helpt de index u niet. Naar analogie is het alsof je in een telefoonboek zoekt naar alle mensen met een bepaalde tweede naam.

Standaard ANSI SQL vereist dat de kolom waarnaar wordt verwezen deel uitmaakt van een PRIMAIRE SLEUTEL of UNIEKE SLEUTEL, en het vereist dat de kolommen met de refererende sleutel overeenkomen met alle de kolommen van een primaire of unieke beperking in de bovenliggende.

Maar InnoDB is toleranter. Het vereist nog steeds dat de kolom waarnaar wordt verwezen in de bovenliggende tabel wordt geïndexeerd, zodat het opzoeken efficiënt kan zijn, en dat de kolommen waarnaar wordt verwezen, de meest linkse zijn in de index. Maar een niet-unieke index is oké; het is toegestaan ​​voor een externe sleutel om ernaar te verwijzen.

Dit kan leiden tot vreemde gevallen, zoals een onderliggende rij die naar meer dan één rij in de bovenliggende rij verwijst, maar er wordt verwacht dat u dergelijke afwijkingen zult afhandelen.

Ik voel de behoefte om het laatste punt te benadrukken. Je zal ontvang afwijkende gegevens als u externe sleutels definieert voor niet-uniek geïndexeerde kolommen in de bovenliggende. Dit zal er waarschijnlijk toe leiden dat uw zoekopdrachten meerdere keren rijen rapporteren wanneer u joins doet. Gebruik dit gedrag van InnoDB niet; u moet alleen externe sleutels definiëren voor bovenliggende kolommen die uniek zijn.




  1. SQL-tijd overschrijdt

  2. hoe waarde te krijgen in array van individuele query

  3. Problemen bij het invoegen van utf-8-tekenreeks in de database en vervolgens uitvoeren naar webpagina

  4. Symfony2 Doctrine voert SQL uit vanuit een bestand in CLI