sql >> Databasteknik >  >> RDS >> Mysql

Mysql och FK:s problem

Kolumnen/kolumnerna för främmande nyckel måste referera till kolumner som består av ett prefix längst till vänster av primärnyckeln eller en unik nyckel i den överordnade tabellen.

Med andra ord, följande exempel fungerar i 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

Du fick ett fel eftersom du försöker göra motsvarande (x) referenser Foo(b).
Din kolumn codmenuitem är den andra av tre kolumner i primärnyckeln för föräldern.

Det skulle fungera om smenuitememp.codemenuitem skulle referera till smenuitem.codmodulo , eftersom den kolumnen är kolumnen längst till vänster i den överordnade tabellens primärnyckel.

Angående din följdfråga:

Tänk på hur främmande nycklar fungerar. Varje gång du infogar eller uppdaterar en rad i den underordnade tabellen måste den slå upp en rad i den överordnade tabellen för att verifiera att värdet finns i den refererade kolumnen. Om kolumnen inte är indexerad måste den göra en tabellskanning för att uppnå denna uppslagning, och det skulle bli mycket dyrt, förutsatt att din överordnade tabell växer.

Om du försöker slå upp en rad baserad på mittkolumnen i ett index med flera kolumner, hjälper indexet dig inte. I analogi är det som att söka i en telefonbok efter alla personer med ett visst mellannamn.

Standard ANSI SQL kräver att den refererade kolumnen är en del av en PRIMARY KEY eller UNIQUE KEY, och det kräver att de främmande nyckelkolumnerna matchar alla kolumnerna för en primär eller unik begränsning i den överordnade.

Men InnoDB är mer tillåtande. Det kräver fortfarande att den refererade kolumnen i den överordnade tabellen indexeras så att uppslagningen kan vara effektiv, och att de refererade kolumnerna är längst till vänster i indexet. Men ett icke-unikt index är okej; det är tillåtet för en främmande nyckel att referera till den.

Detta kan leda till konstiga fall som en underordnad rad som refererar till mer än en rad i föräldern, men det förväntas att du kommer att hantera sådana avvikelser.

Jag känner ett behov av att betona den sista punkten. Du kommer få avvikande data om du definierar främmande nycklar till icke-unikt indexerade kolumner i den överordnade. Detta kommer förmodligen att få dina frågor att rapportera rader flera gånger när du går med. Du bör inte använda detta beteende hos InnoDB; du bör definiera främmande nycklar endast för överordnade kolumner som är unika.




  1. Uttryck en CTE med Arel

  2. Felaktigt datum/tidsvärde:''2012-07-14 23:00:00''

  3. FEL 1452 (23000):Det går inte att lägga till eller uppdatera en underordnad rad:en begränsning av främmande nyckel misslyckas

  4. Felsökning Olaglig blandning av sorteringsfel i mysql