Колоната(ите) на външния ключ трябва да препраща към колона(и), съдържаща най-ляв префикс на първичния ключ или уникален ключ в родителската таблица.
С други думи, следните примери работят в 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
Получавате грешка, защото се опитвате да направите еквивалента на (x) препратки Foo(b).
Вашата колона codmenuitem е втората от трите колони в първичния ключ на родителя.
Ще работи, ако smenuitememp.codemenuitem
трябваше да препращат към smenuitem.codmodulo
, защото тази колона е най-лявата колона в първичния ключ на родителската таблица.
Повторете вашия допълнителен въпрос:
Имайте предвид начина, по който работят външните ключове. Всеки път, когато вмъкнете или актуализирате ред в дъщерната таблица, той трябва да потърси ред в родителската таблица, за да провери дали стойността съществува в референтната колона. Ако колоната не е индексирана, ще трябва да направи сканиране на таблица, за да постигне това търсене, а това би било много скъпо, ако приемем, че вашата родителска таблица расте.
Ако се опитате да търсите ред въз основа на средната колона на индекс с няколко колони, индексът не ви помага. По аналогия, това е като да търсите в телефонния указател всички хора с определено бащино име.
Стандартният ANSI SQL изисква референтната колона да бъде част от ПРЪВЪРЧЕН КЛЮЧ или УНИКАЛЕН КЛЮЧ и изисква колоните с външен ключ да съвпадат с всички колоните на основно или уникално ограничение в родителя.
Но InnoDB е по-разрешаващ. Все още изисква препратената колона в родителската таблица да бъде индексирана, така че търсенето да може да бъде ефективно, и че посочените колони са най-левите в индекса. Но неуникалният индекс е добре; позволено е външен ключ да го препраща.
Това може да доведе до странни случаи като дъщерен ред, който препраща към повече от един ред в родителския, но се очаква да се справите с такива аномалии.
Чувствам необходимост да подчертая последната точка. Вие ще получавате аномални данни, ако дефинирате външни ключове за неуникално индексирани колони в родителя. Това вероятно ще накара вашите заявки да докладват редове многократно, когато правите обединения. Не трябва да използвате това поведение на InnoDB; трябва да дефинирате външни ключове само за родителски колони, които са уникални.