Kolumny klucza obcego muszą odwoływać się do kolumn zawierających skrajny lewy przedrostek klucza podstawowego lub klucz unikalny w tabeli nadrzędnej.
Innymi słowy, w InnoDB działają następujące przykłady:
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
Wystąpił błąd, ponieważ próbujesz wykonać odpowiednik (x) referencji Foo(b).
Twoja kolumna codmenuitem jest drugą z trzech kolumn w kluczu podstawowym elementu nadrzędnego.
Działałoby, gdyby smenuitememp.codemenuitem
miały odwoływać się do smenuitem.codmodulo
, ponieważ ta kolumna jest skrajnie lewą kolumną w kluczu podstawowym tabeli nadrzędnej.
Twoje pytanie uzupełniające:
Pamiętaj, jak działają klucze obce. Za każdym razem, gdy wstawiasz lub aktualizujesz wiersz w tabeli podrzędnej, należy wyszukać wiersz w tabeli nadrzędnej, aby sprawdzić, czy wartość istnieje w kolumnie, do której istnieje odwołanie. Jeśli kolumna nie jest indeksowana, będzie musiała wykonać skanowanie tabeli, aby uzyskać to wyszukiwanie, a to byłoby bardzo kosztowne, zakładając, że Twoja tabela nadrzędna rośnie.
Jeśli spróbujesz wyszukać wiersz na podstawie środkowej kolumny wielokolumnowego indeksu, indeks nie pomoże. Przez analogię jest to jak przeszukiwanie książki telefonicznej wszystkich osób o określonym drugim imieniu.
Standard ANSI SQL wymaga, aby przywoływana kolumna była częścią PRIMARY KEY lub UNIQUE KEY i wymaga, aby kolumny klucza obcego pasowały do wszystkie kolumny podstawowego lub unikatowego ograniczenia w rodzicu.
Ale InnoDB jest bardziej liberalny. Nadal wymaga indeksowania kolumny odniesienia w tabeli nadrzędnej, aby wyszukiwanie było wydajne i że kolumny, do których się odwołuje, znajdują się najdalej od lewej w indeksie. Ale nieunikalny indeks jest w porządku; klucz obcy może się do niego odwoływać.
Może to prowadzić do dziwnych przypadków, takich jak wiersz podrzędny, który odwołuje się do więcej niż jednego wiersza w rzędzie nadrzędnym, ale oczekuje się, że poradzisz sobie z takimi anomaliami.
Czuję potrzebę podkreślenia ostatniego punktu. będziesz uzyskać nietypowe dane, jeśli zdefiniujesz klucze obce do niejednoznacznie indeksowanych kolumn w rodzicu. Prawdopodobnie spowoduje to, że Twoje zapytania będą wielokrotnie raportować wiersze, gdy wykonasz sprzężenia. Nie powinieneś używać tego zachowania InnoDB; powinieneś zdefiniować klucze obce tylko dla kolumn nadrzędnych, które są unikalne.