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

cizí klíče MySQL

Cizí klíče jsou nedílnou součástí vytváření vztahu v relačních databázích. Zde je důvod a jak je vytvořit.

Takže jsme zjistili, že primární klíč poskytuje jedinečný identifikátor pro tabulku. Primární klíče však nejsou jediným typem „klíče“. Naše databáze může obsahovat i cizí klíče.

Co je cizí klíč?

cizí klíč je sloupec (nebo kolekce sloupců) v jedné tabulce, který jednoznačně identifikuje řádek jiné tabulky. Toto definuje vztah mezi dvěma tabulkami.

Cizí klíč umožňuje křížové odkazy na související data napříč tabulkami. To se hodí, když sloupec obsahuje data, která jsou reprezentována v jiné tabulce.

Příklad

Zde je schéma našeho FruitShopu databáze zobrazující vztah mezi Ovoce tabulka a Jednotky stůl.

Černá čára, která spojuje dvě tabulky, označuje cizí klíč. UnitId v poli Ovoce tabulka je cizí klíč k UnitId v poli Jednotky stůl. Tedy hodnotu, kterou vložíme do Fruit.UnitId musí odpovídat hodnotě v Units.UnitId . To aktivuje Fruit.UnitId odkazovat na data v ostatních sloupcích daného záznamu (tj. záznam, který má odpovídající UnitId ).

Data

Pokud tedy naše Ovoce tabulka obsahuje záznam, jako je tento:

FruitId Název ovoce Inventář UnitId DateEntered Datum aktualizováno
1 Apple 10 3 27. 11. 2012 12:42:10 27. 11. 2012 12:42:10

A naše Jednotky tabulka obsahuje následující záznamy:

UnitId UnitName DateEntered Datum aktualizováno
1 Kus 2011-12-30 12:46:15 2011-12-30 12:46:15
2 Skupina 2011-12-30 12:46:15 2011-12-30 12:46:15
3 Kilogram 2011-12-30 12:46:15 2011-12-30 12:46:15
4 Kontejner 2011-12-30 12:46:15 2011-12-30 12:46:15
5 Libra 2011-12-30 12:46:15 2011-12-30 12:46:15
6 Unce 2011-12-30 12:46:15 2011-12-30 12:46:15

Můžete vidět, že Fruit.UnitId pole obsahuje 3 . Nyní se podívejte na Jednotky tabulka pro záznam, který obsahuje 3 v UnitId pole. Můžete vidět, že tento záznam představuje Kilogram . Proto nyní víme, že jablka se měří v kilogramech.

Dobrá věc na nastavení databáze tímto způsobem je, že nemusíme opakovat "Kilogramy" pro každý záznam, který používá tuto jednotku. Omezení duplikace je klíčovou výhodou systémů pro správu relačních databází.

Zobrazení co největšího počtu záznamů v Ovoce tabulka bude sdílet stejný název jednotky (např. "Kilogramy", "Kontejner", "Bunch" atd.), měli bychom si před přidáním duplikátů do naší databáze dobře rozmyslet. Bez použití vztahu cizího klíče bychom mohli jednoduše napsat názvy jednotek přímo do Ovoce tabulky (a případně nazvat sloupec "Unit", "UnitType" nebo "UnitName"). Pak bychom skončili s mnoha záznamy sdílejícími stejnou hodnotu pro sloupec názvu jednotky. Viděli bychom "Kilogram" opakující se znovu a znovu proti mnoha záznamům. Také bychom viděli opakování „Bunch“ a jakýkoli jiný oblíbený typ jednotky.

I když to nemusí být nutně „špatné“, je obecně efektivnější uložit jeden záznam pro každý z těchto názvů jednotek do samostatné tabulky a poté na tuto tabulku odkazovat pomocí UnitId sloupec. Je to efektivnější než opakování těchto názvů jednotek znovu a znovu pro každý záznam vytvořený v Fruits stůl. Usnadní to také, pokud se někdy rozhodneme aktualizovat název jednotky (například změnit „Kilogramy“ na „Kila“). Pokud aktualizujeme název jednotky, neovlivní to Ovoce tabulka, protože UnitId zůstane stejný. Navíc to také pomáhá předcházet tomu, aby se v naší databázi objevovala nekonzistentní data.

Omezení cizího klíče

Omezení cizího klíče je databázový objekt, který pomáhá udržovat data cizího klíče konzistentní. Chcete-li zachovat referenční integritu, vytvoříte omezení cizího klíče. Vytvořením omezení cizího klíče říkáte MySQL, aby prosazovala určitá pravidla nad daty. Když jsou data vložena, odstraněna nebo aktualizována, MySQL zkontroluje, zda se drží cizího klíče, který jste vytvořili mezi tabulkami. Pokud ne, zabrání to zápisu/přepsání/vymazání dat, čímž se zachová referenční integrita.

Pokud se například uživatel pokusí zadat hodnotu UnitId do Fruit.UnitId ale v Units.UnitId není žádný odpovídající záznam sloupec, pak MySQL zabrání uživateli zadat tuto hodnotu.

Když jsme vytvořili naše dvě tabulky, přidali jsme do Ovoce omezení cizího klíče stůl. Zde je kód, který jsme použili k vytvoření omezení:

CONSTRAINT fkFruitUnits FOREIGN KEY (UnitId) REFERENCES Units (UnitId) ON DELETE RESTRICT ON UPDATE CASCADE

Když rozbalíte uzly v levém SCHÉMA můžete vidět cizí klíč, který jsme vytvořili (a také primární klíče):

Pokud se pokusíte vložit data, která neodpovídají omezení cizího klíče, měla by se zobrazit chyba.

Pokud se například pokusím vložit záznam do Ovoce tabulky pomocí UnitId hodnota, která neexistuje v Jednotkách tabulky, zobrazí se mi následující chyba:

K tomu dochází, protože se snažím vložit hodnotu 5 do UnitId pokud v Units.UnitId není žádná odpovídající hodnota pole.

Aby to uspělo, musel bych zajistit, aby byl záznam v Units tabulka s UnitId z 5 .

Cizí klíč nefunguje?

Občas se můžete setkat se situací, kdy se zdá, že cizí klíč nefunguje. Můžete například úspěšně vložit data do tabulky, i když existuje cizí klíč, který by měl zabránit vložení těchto dat.

V této situaci můžete zkontrolovat několik věcí.

  • Ujistěte se, že jste přidali ON DELETE a ON UPDATE klauzule ve vašem kódu. Například ON DELETE RESTRICT ON UPDATE CASCADE . Podívejte se na náš příklad CREATE TABLE, kde je uvedeno, kdy tento kód umístit.
  • Ujistěte se, že tabulka je InnoDB . Můžete to udělat přidáním ENGINE=InnoDB na konec vaší CREATE TABLE příkaz (viz můj příklad z doby, kdy jsme vytvářeli naše tabulky). Některé motory (například MyISAM ) nepodporují omezení cizího klíče, ale neposkytují na to žádné varování, když se pokusíte vytvořit omezení cizího klíče. Pokud váš výchozí engine není InnoDB pak je pravděpodobné, že vaše cizí klíče nebudou podporovány.
  • Ujistěte se, že MySQL skutečně kontroluje cizí klíče. Můžete to provést spuštěním následujícího kódu:SET FOREIGN_KEY_CHECKS=1 .

Zakázat kontrolu cizího klíče

Mohou nastat situace, kdy se omezení cizích klíčů mohou stát zbytečně omezujícími – do té míry, že vážně naruší vaše úsilí při načítání dat. Například když jste právě vytvořili databázi a potřebujete načíst počáteční data. Nebo pokud potřebujete odstranit spoustu tabulek a znovu načíst data.

Pokud nenačtete data ve správném pořadí, budete pravděpodobně stále dostávat chyby cizího klíče v důsledku načítání dat ve špatném pořadí (tj. pokoušíte se načíst podřízené tabulky dříve, než budou mít nadřazené tabulky své data načtena).

Toto není problém pouze při načítání data. S tímto problémem se také můžete setkat při vytváření databáze. Pokud nevytvoříte tabulky ve správném pořadí, můžete narazit na chyby kvůli omezení cizího klíče.

Pokud neznáte správné pořadí rodič-dítě, může stanovení správného pořadí vytvoření databáze nebo načtení dat zabrat spoustu času a úsilí. V případech, jako jsou tyto, možná bude lepší říct MySQL dočasně, aby prozatím nekontrolovala cizí klíče.

Kontrolu cizího klíče můžete zakázat pomocí následujícího kódu:

FOREIGN_KEY_CHECKS=0

Chcete-li jej znovu aktivovat, postupujte takto:

FOREIGN_KEY_CHECKS=1

  1. listview zobrazí data z databáze v Androidu

  2. Používání Microsoft Access s Power BI

  3. Prevence sousedících/překrývajících se položek pomocí EXCLUDE v PostgreSQL

  4. jak vybrat sudé záznamy z tabulky v oracle?