V tomto článku demonstruji, jak vytvořit cizí klíč v SQL Server pomocí Transact-SQL. Ukazuji, jak vytvořit cizí klíč při vytváření tabulky (na rozdíl od aktualizace existující tabulky).
Cizí klíč je sloupec, který odkazuje na sloupec primárního klíče jiné tabulky. Tím se vytvoří vztah mezi tabulkami.
Příklad 1 – Příprava
V tomto příkladu vytvořím testovací databázi s jednou tabulkou. Tato tabulka bude obsahovat primární klíč, na který bude odkazovat náš cizí klíč.
Vytvořte databázi:
VYTVOŘTE DATABÁZI FK_Test;
Nyní vytvořte tabulku primárního klíče:
POUŽÍVEJTE FK_Test;CREATE TABLE Země( CountryId int IDENTITY (1,1) NOT NULL PRIMARY KEY, CountryName nvarchar(60));
Příklad 2 – Vytvoření cizího klíče
Nyní, když máme tabulku s primárním klíčem, vytvořme další tabulku s cizím klíčem, která na tento primární klíč odkazuje.
VYTVOŘIT TABULKU Město( CityId int IDENTITY (1,1) NENÍ NULL PRIMÁRNÍ KLÍČ, CountryId int NOT NULL REFERENCE Country(CountryId), CityName nvarchar(60));
Toto je nejjednodušší způsob, jak vytvořit cizí klíč. Vše, co děláme, je přidat REFERENCES
klauzule (spolu s tabulkou a sloupcem primárního klíče) do sloupce, který bude mít omezení cizího klíče.
Aby bylo jasno, část, která definuje cizí klíč, je tato:
REFERENCE Country(CountryId)
Toto je zahrnuto v definici sloupce a jednoduše uvádí, že tento sloupec bude odkazovat na CountryId
ve sloupci Country
tabulka.
V tomto případě mají cizí klíč i primární klíč, na který odkazuje, stejný název (CountryId
). Není to však podmínkou – váš sloupec cizího klíče může mít zcela jiný název než sloupec, na který odkazuje (ačkoli všechny sloupce účastnící se vztahu cizího klíče musí být definovány se stejnou délkou a měřítkem).
Tento příklad způsobí, že SQL Server automaticky vygeneruje název cizího klíče. To proto, že jsem neuvedl jméno. Čtěte dále a zjistěte, jak můžete vytvořit název pro svůj cizí klíč.
Nejprve se však podívejme na omezení cizího klíče, které jsme právě vytvořili.
Příklad 3 – Kontrola omezení cizího klíče
Existuje mnoho způsobů, jak vrátit cizí klíč pomocí T-SQL, a zde je jeden z nich:
EXEC sp_fkeys @fktable_name =Město;
Výsledek (při použití vertikálního výstupu):
PKTABLE_QUALIFIER | FK_TestPKTABLE_OWNER | dboPKTABLE_NAME | ZeměPKCOLUMN_NAME | CountryIdFKTABLE_QUALIFIER | FK_TestFKTABLE_OWNER | dboFKTABLE_NAME | MěstoFKCOLUMN_NAME | CountryIdKEY_SEQ | 1UPDATE_RULE | 1DELETE_RULE | 1FK_NAME | FK__City__CountryId__38996AB5PK_NAME | PK__Country__10D1609FC8BFA7F2ODLOŽENÍ | 7
sp_fkeys
systémová uložená procedura vrací informace o našem cizím klíči, jeho přidruženém primárním klíči a další relevantní podrobnosti. Jednoduše předáte název tabulky cizích klíčů nebo tabulky primárních klíčů a ta vrátí relevantní informace.
V tomto příkladu předám název tabulky cizích klíčů – City
. Ve výsledcích se můžeme podívat na
FK_NAME
sloupec, abyste viděli, že tato tabulka má omezení cizího klíče s názvem
FK__City__CountryId__38996AB5
. Toto je ten, který jsme právě vytvořili.
Takže teď, když jsme vytvořili cizí klíč, kdykoli se pokusíme vložit nebo aktualizovat hodnotu do City.CountryId
omezení cizího klíče to umožní pouze v případě, že stejná hodnota již existuje v Country.CountryId
sloupec. To zajišťuje zachování referenční integrity v rámci databáze.
Příklad 4 – Další možnosti
K definici cizího klíče je možné přidat další možnosti.
Můžete například zadat název cizího klíče. Můžete také určit, co se má stát s hodnotami v tomto sloupci, pokud je odpovídající hodnota v primárním klíči aktualizována nebo odstraněna.
Zde znovu vytvořím obě tabulky, ale tentokrát výslovně specifikuji tyto možnosti (totéž dělám pro primární klíče):
VYTVOŘIT TABULKU Země( CountryId int IDENTITY (1,1) NOT NULL, CONSTRAINT PK_Country_CountryId PRIMÁRNÍ KLÍČ SE SLUSTROVANÝ (CountryId), CountryName nvarchar(60));CREATE TABLE City( CityId int IDENTITY (1,1) NOT CONINT PK_City_CityId PRIMÁRNÍ KLÍČ CLUSTERED (CityId), CountryId int NENÍ NULL, OMEZENÍ FK_City_Country CIZÍ KLÍČ (CountryID) REFERENCE Země (CountryID) PŘI SMAZÁNÍ KASKÁDY PŘI AKTUALIZACI KASKÁDY, CityName nvarchar(60));V tomto případě definice cizího klíče začíná
CONSTRAINT
, za kterým následuje název cizího klíče a za nímFOREIGN KEY
, následovaný sloupcem, na který bude aplikováno omezení cizího klíče (vloženo do závorek).Potom vidíme stejné
REFERENCES
klauzuli, kterou jsme viděli v předchozím příkladu.
ON DELETE CASCADE
aON UPDATE CASCADE
klauzule se používají k zajištění provedení změn vCountry
tabulky jsou automaticky přeneseny doCity
stůl. Pokud je například odstraněn řádek z nadřazené tabulky (primární klíč), všechny odpovídající řádky jsou odstraněny z referenční tabulky (cizí klíč).Výchozí hodnota pro
ON DELETE
aON UPDATE
jeNO ACTION
. V tomto případě Database Engine vyvolá chybu a akce aktualizace nebo odstranění na řádku v nadřazené tabulce je vrácena zpět.Můžete také použít
SET NULL
pro nastavení sloupce cizího klíče naNULL
(vyžaduje, aby sloupec cizího klíče měl hodnotu null), neboSET DEFAULT
nastavte jej na výchozí hodnotu (vyžaduje, aby měl sloupec cizího klíče výchozí definici. Pokud sloupec má hodnotu null a není nastavena žádná explicitní výchozí hodnota,NULL
se stane implicitní výchozí hodnotou sloupce).V tomto příkladu jsem také využil příležitosti pojmenovat primární klíče. Můžete vidět, že syntaxe primárního klíče je podobná syntaxi cizího klíče, ale bez
REFERENCES
klauzule (a s přidanýmCLUSTERED
argument, což je výchozí nastavení pro primární klíče).Nyní zkontrolujte cizí klíč:
EXEC sp_fkeys @fktable_name =Město;Výsledek:
PKTABLE_QUALIFIER | FK_TestPKTABLE_OWNER | dboPKTABLE_NAME | ZeměPKCOLUMN_NAME | CountryIdFKTABLE_QUALIFIER | FK_TestFKTABLE_OWNER | dboFKTABLE_NAME | MěstoFKCOLUMN_NAME | CountryIdKEY_SEQ | 1UPDATE_RULE | 0DELETE_RULE | 0FK_NAME | FK_City_CountryPK_NAME | PK_Country_CountryIdDEFERRABILITY | 7Vidíme, že název cizího klíče je nyní FK_City_Country a omezení primárního klíče sloupce, na který odkazuje, se nazývá PK_Country_CountryId .
Příklad 5 – Cizí klíč ve více sloupcích
Můžete také vytvořit cizí klíč ve více sloupcích, který odkazuje na primární klíč s více sloupci. Vícesloupcové primární klíče jsou také známé jako složené primární klíče. Chcete-li vytvořit složený cizí klíč, jednoduše při definování klíče oddělte sloupce čárkou.
Takhle:
CONSTRAINT FK_FKName CIZÍ KLÍČ (FKColumn1, FKColumn2)REFERENCE PrimaryKeyTable (PKColumn1, PKColumn2)Podrobnější příklad naleznete v části Jak vytvořit složený cizí klíč na serveru SQL.
Je primární klíč skutečně nezbytný?
Primární klíč není pro cizí klíče nezbytně nutný, protože můžete použít jedinečné omezení nebo jedinečný index. Konkrétně dokumentace společnosti Microsoft uvádí toto:
FOREIGN KEY
omezení mohou odkazovat pouze na sloupce vPRIMARY KEY
neboUNIQUE
omezení v odkazované tabulce nebo vUNIQUE INDEX
v odkazované tabulce.I když je tedy obvykle dobrým zvykem mít primární klíče na všech tabulkách, vaše cizí klíče na ně odkazovat nemusí.