Mysql
 sql >> база данни >  >> RDS >> Mysql

Mysql и проблемът на FK

Колоната(ите) на външния ключ трябва да препраща към колона(и), съдържаща най-ляв префикс на първичния ключ или уникален ключ в родителската таблица.

С други думи, следните примери работят в 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; трябва да дефинирате външни ключове само за родителски колони, които са уникални.




  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Затваряне на JDBC връзки в пула

  2. Мокнете MySQL база данни в Python

  3. Java ZonedDateTime запишете в базата данни

  4. MySQL множество индекси срещу индекс с няколко колони за търсене

  5. Използвате ли правилно класове в други класове в php?