Die Fremdschlüsselspalte(n) muss/müssen auf Spalten verweisen, die ein ganz linkes Präfix des Primärschlüssels oder einen eindeutigen Schlüssel in der übergeordneten Tabelle enthalten.
Mit anderen Worten, die folgenden Beispiele funktionieren 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
Sie haben einen Fehler erhalten, weil Sie versuchen, das Äquivalent von (x) auf Foo(b) zu verweisen.
Ihre Spalte codmenuitem ist die zweite von drei Spalten im Primärschlüssel des übergeordneten Schlüssels.
Es würde funktionieren, wenn smenuitememp.codemenuitem
sollten smenuitem.codmodulo
referenzieren , da diese Spalte die Spalte ganz links im Primärschlüssel der übergeordneten Tabelle ist.
Zu Ihrer Folgefrage:
Denken Sie daran, wie Fremdschlüssel funktionieren. Jedes Mal, wenn Sie eine Zeile in der untergeordneten Tabelle einfügen oder aktualisieren, muss eine Zeile in der übergeordneten Tabelle nachgeschlagen werden, um zu überprüfen, ob der Wert in der referenzierten Spalte vorhanden ist. Wenn die Spalte nicht indiziert ist, muss sie einen Tabellenscan durchführen, um diese Suche zu erreichen, und das wäre sehr teuer, vorausgesetzt, Ihre übergeordnete Tabelle wächst.
Wenn Sie versuchen, eine Zeile basierend auf der mittleren Spalte eines mehrspaltigen Index nachzuschlagen, hilft Ihnen der Index nicht weiter. Analog dazu ist es, als würde man in einem Telefonbuch nach allen Personen mit einem bestimmten zweiten Vornamen suchen.
Standard-ANSI-SQL erfordert, dass die referenzierte Spalte Teil eines PRIMARY KEY oder UNIQUE KEY ist, und es erfordert, dass die Fremdschlüsselspalten mit allen übereinstimmen die Spalten einer primären oder eindeutigen Einschränkung im übergeordneten Element.
Aber InnoDB ist freizügiger. Es erfordert immer noch, dass die referenzierte Spalte in der übergeordneten Tabelle indiziert wird, damit die Suche effizient sein kann, und dass die referenzierten Spalten ganz links im Index stehen. Aber ein nicht eindeutiger Index ist in Ordnung; Es ist zulässig, dass ein Fremdschlüssel darauf verweist.
Dies kann zu seltsamen Fällen führen, wie z. B. einer untergeordneten Zeile, die auf mehr als eine Zeile in der übergeordneten Zeile verweist, aber es wird erwartet, dass Sie mit solchen Anomalien umgehen.
Ich fühle mich verpflichtet, den letzten Punkt hervorzuheben. Sie werden Anomale Daten erhalten, wenn Sie Fremdschlüssel für nicht eindeutig indizierte Spalten im übergeordneten Element definieren. Dies wird wahrscheinlich dazu führen, dass Ihre Abfragen Zeilen mehrmals melden, wenn Sie Joins durchführen. Sie sollten dieses Verhalten von InnoDB nicht verwenden; Sie sollten Fremdschlüssel nur für eindeutige übergeordnete Spalten definieren.