如何在 SQL Server 中创建外键(T-SQL 示例)
在本文中,我将演示如何使用 Transact-SQL 在 SQL Server 中创建外键。我演示了如何在创建表时创建外键(而不是更新现有表)。
示例 1 – 准备
在此示例中,我将创建一个带有一个表的测试数据库。此表将包含我们的外键将引用的主键。
创建数据库:
CREATE DATABASE FK_Test;
现在创建主键表:
USE FK_Test;
CREATE TABLE Country ( CountryId int IDENTITY (1,1) NOT NULL PRIMARY KEY, CountryName nvarchar(60) );
示例 2 – 创建外键
现在我们已经得到了一个带有主键的表,让我们创建另一个表,其中包含引用该主键的外键。
CREATE TABLE City ( CityId int IDENTITY (1,1) NOT NULL PRIMARY KEY, CountryId int NOT NULL REFERENCES Country(CountryId), CityName nvarchar(60) );
这是创建外键的最简单方法。我们要做的就是将子句(以及主键表和列)添加到将具有外键约束的列中。REFERENCES
需要明确的是,定义外键的部分是这样的:
REFERENCES Country(CountryId)
这包含在列定义中,只是声明此列将引用表中的列。CountryId``Country
在这个示例中,外键和它引用的主键共享相同的名称 ()。但是,这不是必需的 – 外键列的名称可以与其引用的列完全不同(尽管必须使用相同的长度和小数位数定义参与外键关系的所有列)。CountryId
此示例使 SQL Server 自动生成外键的名称。那是因为我没有提供名字。请继续阅读,了解如何为外键创建名称。
但首先,让我们检查一下刚刚创建的外键约束。
示例 3 – 检查外键约束
使用 T-SQL 返回外键的方法有很多种,下面是其中之一:
EXEC sp_fkeys @fktable_name = City;
结果(使用垂直输出):
PKTABLE_QUALIFIER | FK_Test PKTABLE_OWNER | dbo PKTABLE_NAME | Country PKCOLUMN_NAME | CountryId FKTABLE_QUALIFIER | FK_Test FKTABLE_OWNER | dbo FKTABLE_NAME | City FKCOLUMN_NAME | CountryId KEY_SEQ | 1 UPDATE_RULE | 1 DELETE_RULE | 1 FK_NAME | FK__City__CountryId__38996AB5 PK_NAME | PK__Country__10D1609FC8BFA7F2 DEFERRABILITY | 7
系统存储过程返回有关外键、其关联的主键和其他相关详细信息的信息。您只需传入外键表或主键表的名称,它就会返回相关信息。sp_fkeys
在此示例中,我传递外键表的名称 – 。在结果中,我们可以查看该列,看看这个表有一个名为 的外键约束。这是我们刚刚创建的那个。CityFK_NAMEFK__City__CountryId__38996AB5
因此,既然我们已经创建了外键,那么每当我们尝试在列中插入或更新值时,外键约束只有在列中已存在相同值时才允许它。这可确保在数据库中维护引用完整性。City.CountryId``Country.CountryId
示例 4 – 更多选项
可以向外键定义添加更多选项。
例如,您可以提供外键的名称。您还可以指定在更新或删除主键中的相应值时此列中的值应发生的情况。
在这里,我再次创建这两个表,但这次我显式指定了这些选项(我对主键执行相同的操作):
CREATE TABLE Country ( CountryId int IDENTITY (1,1) NOT NULL, CONSTRAINT PK_Country_CountryId PRIMARY KEY CLUSTERED (CountryId), CountryName nvarchar(60) );
CREATE TABLE City ( CityId int IDENTITY (1,1) NOT NULL, CONSTRAINT PK_City_CityId PRIMARY KEY CLUSTERED (CityId), CountryId int NOT NULL, CONSTRAINT FK_City_Country FOREIGN KEY (CountryID) REFERENCES Country (CountryID) ON DELETE CASCADE ON UPDATE CASCADE, CityName nvarchar(60) );
在这个示例中,外键定义以 开头,后跟外键的名称,后跟 ,后跟将应用外键约束的列(插入括号中)。CONSTRAINT``FOREIGN KEY
然后,我们看到在上一个示例中看到的相同子句。REFERENCES
and 子句用于确保对表所做的更改自动传播到表中。例如,如果从父(主键)表中删除一行,则会从引用(外键)表中删除任何相应的行。ON DELETE CASCADE``ON UPDATE CASCADE``Country``City
和 的缺省值为 。在这种情况下,数据库引擎会引发错误,并对父表中的行执行更新或删除操作。ON DELETE``ON UPDATE``NO ACTION
还可以使用 将外键列设置为 (要求外键列可为 null),或将其设置为其默认值(要求外键列具有默认定义。如果列可为 null,并且没有设置显式默认值,则将成为该列的隐式默认值)。SET NULL``NULL``SET DEFAULT``NULL
在此示例中,我还借此机会命名了主键。您可以看到主键语法类似于外键语法,但没有子句(并且带有添加的参数,这是主键的默认值)。REFERENCES``CLUSTERED
现在检查外键:
EXEC sp_fkeys @fktable_name = City;
输出:
PKTABLE_QUALIFIER | FK_Test
PKTABLE_OWNER | dbo
PKTABLE_NAME | Country
PKCOLUMN_NAME | CountryId
FKTABLE_QUALIFIER | FK_Test
FKTABLE_OWNER | dbo
FKTABLE_NAME | City
FKCOLUMN_NAME | CountryId
KEY_SEQ | 1
UPDATE_RULE | 0
DELETE_RULE | 0
FK_NAME | FK_City_Country
PK_NAME | PK_Country_CountryId
DEFERRABILITY | 7我们可以看到外键的名称现在是,它引用的列的主键约束称为 。FK_City_CountryPK_Country_CountryId
示例 5 – 多列上的外键
还可以在引用多列主键的多个列上创建外键。多列主键也称为复合主键。若要创建复合外键,只需在定义键时用逗号分隔列。
示例如下:
CONSTRAINT FK_FKName FOREIGN KEY (FKColumn1, FKColumn2) REFERENCES PrimaryKeyTable (PKColumn1, PKColumn2)
有关更详细的示例,请参阅如何在 SQL Server 中创建复合外键。
主键真的有必要吗?
主键对于外键不是绝对必需的,因为可以使用唯一约束或唯一索引。具体来说,微软文档指出:
FOREIGN KEY约束只能引用引用表中的列或约束,或者引用表上的 中的约束。PRIMARY KEY``UNIQUE``UNIQUE INDEX
因此,虽然在所有表上都有主键通常是一种很好的做法,但外键没有义务引用它们。