В тази статия демонстрирам как да създадете външен ключ в SQL Server с помощта на Transact-SQL. Демонстрирам как се създава външен ключ в момента на създаване на таблицата (за разлика от актуализирането на съществуваща таблица).
Външният ключ е колона, която препраща към колоната с първичен ключ на друга таблица. Това създава връзка между таблиците.
Пример 1 – Подготовка
В този пример ще създам тестова база данни с една таблица. Тази таблица ще съдържа първичния ключ, който нашият външен ключ ще препраща.
Създайте базата данни:
СЪЗДАВАНЕ НА БАЗА ДАННИ FK_Test;
Сега създайте таблицата с първичен ключ:
ИЗПОЛЗВАЙТЕ FK_Test;СЪЗДАЙТЕ ТАБЛИЦА Country( CountryId int IDENTITY (1,1) NOT NULL PRIMARY KEY, CountryName nvarchar(60));
Пример 2 – Създаване на външния ключ
Сега, когато имаме таблица с първичен ключ, нека създадем друга таблица с външен ключ, който препраща към този първичен ключ.
СЪЗДАВАНЕ НА ТАБЛИЦА Град( CityId int IDENTITY (1,1) NOT NULL PRIMARY KEY, CountryId int NOT NULL REFERENCE Country(CountryId), CityName nvarchar(60));
Това е най-простият начин за създаване на външен ключ. Всичко, което правим, е да добавим REFERENCES
клауза (заедно с таблицата и колоната с първичен ключ) към колоната, която ще има ограничението за външен ключ.
За да бъде ясно, частта, която дефинира външния ключ, е следната:
РЕФЕРЕНЦИИ Country(CountryId)
Това е включено в дефиницията на колоната и просто посочва, че тази колона ще препраща към CountryId
колона в Country
таблица.
В този случай и външният ключ, и първичният ключ, който препраща, споделят едно и също име (CountryId
). Това обаче не е изискване – вашата колона с външен ключ може да има напълно различно име от колоната, която препраща (въпреки че всички колони, участващи във връзка с външен ключ, трябва да бъдат дефинирани със същата дължина и мащаб).
Този пример кара SQL Server автоматично да генерира името на външния ключ. Това е, защото не посочих име. Прочетете, за да видите как можете да създадете име за вашия външен ключ.
Но първо, нека проверим ограничението на външния ключ, което току-що създадохме.
Пример 3 – Проверете ограничението на външния ключ
Има много начини за връщане на външен ключ с помощта на T-SQL и ето един от тях:
EXEC sp_fkeys @fktable_name =Град;
Резултат (с помощта на вертикален изход):
PKTABLE_QUALIFIER | FK_TestPKTABLE_OWNER | dboPKTABLE_NAME | CountryPKCOLUMN_NAME | CountryIdFKTABLE_QUALIFIER | FK_TestFKTABLE_OWNER | dboFKTABLE_NAME | CityFKCOLUMN_NAME | CountryIdKEY_SEQ | 1UPDATE_RULE | 1DELETE_RULE | 1FK_NAME | FK__City__CountryId__38996AB5PK_NAME | PK__Country__10D1609FC8BFA7F2ОТЛОЖЕНИЕ | 7
sp_fkeys
системната съхранена процедура връща информация за нашия външен ключ, свързания с него първичен ключ и други подходящи подробности. Просто предавате името на таблицата с външни ключове или таблицата с първичен ключ и тя ще върне съответната информация.
В този пример предавам името на таблицата с външни ключове – City
. В резултатите можем да разгледаме
FK_NAME
колона, за да видите, че тази таблица има ограничение за външен ключ, наречено
FK__City__CountryId__38996AB5
. Това е този, който току-що създадохме.
И така, сега, когато създадохме външния ключ, всеки път, когато се опитаме да вмъкнем или актуализираме стойност в City.CountryId
колона, ограничението на външния ключ ще го позволи само ако същата стойност вече съществува в Country.CountryId
колона. Това гарантира, че референтната цялост се поддържа в базата данни.
Пример 4 – Още опции
Възможно е да добавите повече опции към вашата дефиниция за външен ключ.
Например можете да посочите име за външния ключ. Можете също да посочите какво да се случи със стойностите в тази колона, ако съответната стойност в първичния ключ бъде актуализирана или изтрита.
Тук отново създавам и двете таблици, но този път изрично посочвам тези опции (правя същото за първичните ключове):
СЪЗДАВАНЕ НА ТАБЛИЦА Country( CountryId int IDENTITY (1,1) NOT NULL, CONSTRAINT PK_Country_CountryId ПЪРВИЧЕН КЛУСТЕР (CountryId), CountryName nvarchar(60));CREATE TABLE City( CityId int IDENTITY (1,1) CONSTRAINT NULL PK_City_CityId ПЪРВЕН КЛУСТЕР (CityId), CountryId int NOT NULL, ОГРАНИЧЕНИЕ FK_City_Country ВЪНШЕН КЛЮЧ (CountryID) СПРАВКИ Държава (CountryID) ПРИ ИЗТРИВАНЕ НА КАСКАДА ПРИ АКТУАЛИЗИРАНЕ НА КАСКАДА, CityName0));6)В този случай дефиницията на външния ключ започва с
CONSTRAINT
, последвано от името на външния ключ, последвано отFOREIGN KEY
, последвано от колоната, към която ще бъде приложено ограничението за външния ключ (вмъкнато в скоби).След това виждаме същите
REFERENCES
клауза, която видяхме в предишния пример.
ON DELETE CASCADE
иON UPDATE CASCADE
клаузите се използват, за да се гарантира, че промените, направени вCountry
таблицата автоматично се разпространяват вCity
маса. Например, ако един ред бъде изтрит от таблицата родител (първичен ключ), всички съответни редове се изтриват от таблицата за препращане (външен ключ).Стойността по подразбиране за
ON DELETE
иON UPDATE
еNO ACTION
. В този случай Database Engine повдига грешка и действието за актуализиране или изтриване на реда в родителската таблица се отменя.Можете също да използвате
SET NULL
за да зададете колоната за външен ключ наNULL
(изисква колоната с външния ключ да бъде нула) илиSET DEFAULT
за да го зададете на стойността му по подразбиране (изисква колоната с външния ключ да има дефиниция по подразбиране. Ако колона е нула и няма изрично зададена стойност по подразбиране,NULL
става неявната стойност по подразбиране на колоната).В този пример също се възползвах от възможността да наименувам първичните ключове. Можете да видите, че синтаксисът на първичния ключ е подобен на синтаксиса на външния ключ, но без
REFERENCES
клауза (и с добавенCLUSTERED
аргумент, който е по подразбиране за първични ключове).Сега проверете външния ключ:
EXEC sp_fkeys @fktable_name =Град;Резултат:
PKTABLE_QUALIFIER | FK_TestPKTABLE_OWNER | dboPKTABLE_NAME | CountryPKCOLUMN_NAME | CountryIdFKTABLE_QUALIFIER | FK_TestFKTABLE_OWNER | dboFKTABLE_NAME | CityFKCOLUMN_NAME | CountryIdKEY_SEQ | 1UPDATE_RULE | 0DELETE_RULE | 0FK_NAME | FK_City_CountryPK_NAME | PK_Country_CountryIdDEFERRABILITY | 7Можем да видим, че името на външния ключ вече е FK_City_Country и ограничението на първичния ключ на колоната, която препраща, се нарича PK_Country_CountryId .
Пример 5 – Външен ключ върху множество колони
Можете също да създадете външен ключ в множество колони, който препраща към многоколонен първичен ключ. Многоколонните първични ключове са известни още като съставни първични ключове. За да създадете съставен външен ключ, просто разделете колоните със запетая, когато дефинирате ключа.
Като това:
ОГРАНИЧЕНИЕ FK_FKName ВЪНШЕН КЛЮЧ (FKColumn1, FKColumn2)РЕФЕРЕНЦИИ PrimaryKeyTable (PKColumn1, PKColumn2)Вижте Как да създадете композитен външен ключ в SQL Server за по-подробен пример.
Наистина ли е необходим първичният ключ?
Първичният ключ не е абсолютно необходим за външни ключове, тъй като можете да използвате уникално ограничение или уникален индекс. По-конкретно, документацията на Microsoft гласи това:
FOREIGN KEY
ограниченията могат да препращат само към колони вPRIMARY KEY
илиUNIQUE
ограничения в посочената таблица или вUNIQUE INDEX
на посочената таблица.Така че, докато обикновено е добра практика да имате първични ключове във всички таблици, външните ви ключове не са длъжни да ги препращат.