sql >> Databáze >  >> RDS >> Mysql

Problém Mysql a FK

Sloupce cizího klíče musí odkazovat na sloupce obsahující předponu primárního klíče zcela vlevo nebo jedinečný klíč v nadřazené tabulce.

Jinými slovy, následující příklady fungují v 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

Došlo k chybě, protože se pokoušíte provést ekvivalent (x) odkazů Foo(b).
Váš sloupec codmenuitem je druhý ze tří sloupců v primárním klíči rodiče.

Fungovalo by to, kdyby smenuitememp.codemenuitem odkazovali na smenuitem.codmodulo , protože tento sloupec je sloupcem zcela vlevo v primárním klíči nadřazené tabulky.

K vaší doplňující otázce:

Mějte na paměti, jak fungují cizí klíče. Pokaždé, když vložíte nebo aktualizujete řádek v podřízené tabulce, je třeba vyhledat řádek v nadřazené tabulce, aby ověřil, že hodnota v odkazovaném sloupci existuje. Pokud sloupec není indexován, bude muset provést prohledávání tabulky, aby se dosáhlo tohoto vyhledávání, a to by bylo velmi drahé, za předpokladu, že vaše nadřazená tabulka roste.

Pokud se pokusíte vyhledat řádek podle prostředního sloupce vícesloupcového indexu, index vám nepomůže. Analogicky je to jako hledat v telefonním seznamu všechny lidi s určitým druhým jménem.

Standardní ANSI SQL vyžaduje, aby odkazovaný sloupec byl součástí PRIMARY KEY nebo UNIQUE KEY a vyžaduje, aby se sloupce cizího klíče shodovaly všem sloupce primárního nebo jedinečného omezení v nadřazeném objektu.

Ale InnoDB je tolerantnější. Stále vyžaduje, aby byl odkazovaný sloupec v nadřazené tabulce indexován, aby bylo vyhledávání efektivní, a že odkazované sloupce jsou v indexu úplně vlevo. Ale nejedinečný index je v pořádku; je povoleno, aby na něj odkazoval cizí klíč.

To může vést k podivným případům, jako je podřízený řádek, který odkazuje na více než jeden řádek v nadřazeném řádku, ale očekává se, že takové anomálie zvládnete.

Cítím potřebu zdůraznit poslední bod. budete získáte anomální data, pokud definujete cizí klíče pro nejedinečně indexované sloupce v nadřazeném prvku. To pravděpodobně způsobí, že vaše dotazy budou hlásit řádky vícekrát, když se připojíte. Toto chování InnoDB byste neměli používat; cizí klíče byste měli definovat pouze pro nadřazené sloupce, které jsou jedinečné.




  1. Jak udělat MySQL + podřetězec? + vyměnit?

  2. Poznámky k indexům PostgreSQL B-stromu

  3. Jak opakovat tiskové příkazy při provádění skriptu SQL

  4. Použití PHP ke spuštění více MYSQL dotazů