如何在 SQL Server 中创建主键(T-SQL 示例)
本文演示在使用事务处理 SQL 创建表时如何在 SQL Server 中创建主键。
主键是已配置为给定表的唯一标识符的一个或多个列。主键可用于强制实施表中的数据完整性。
一个表只能有一个主键,并且主键只能添加到定义为 的列中。NOT NULL
本文演示如何在_新_表中创建主键(即在创建表时)。如果需要在_现有_表中创建主键,请参阅如何在 SQL Server 中的现有表中添加主键。
示例 1 – 创建具有主键的表
首先,我将创建一个测试数据库:
CREATE DATABASE PK_Test;
现在创建一个包含主键约束的新表:
USE PK_Test;
CREATE TABLE Colors ( ColorId int IDENTITY (1,1) NOT NULL PRIMARY KEY, ColorName varchar(50) );
这将创建一个名为 Colors 的新表,并在其 ColorId 列上定义主键约束。
示例 2 – 检查主键约束
我们可以运行以下代码来返回数据库中的主键约束列表:
SELECT name, type, unique_index_id, is_system_named FROM sys.key_constraints WHERE type = ‘PK’;
输出:
+------------------------------+--------+-------------------+-------------------+
| name | type | unique_index_id | is_system_named |
|------------------------------+--------+-------------------+-------------------|
| PK__Colors__8DA7674DD34F4585 | PK | 1 | 1 |
+------------------------------+--------+-------------------+-------------------+我已经缩小了此示例的列范围。系统视图返回的列数超过此值。如果您愿意,您始终可以使用通配符返回所有列。sys.key_constraints``*
我们可以通过查询结果看到,这个数据库只有一个主键(我们刚刚创建的那个)。
在这个示例中,系统会自动命名主键。您还可以选择提供自己的姓名(稍后会详细介绍)。
示例 3 – 检查索引
默认情况下,在创建主键时会创建聚集索引。您可以显式指定聚集索引,也可以让它自动创建。您还可以选择指定非聚集索引。
下面是一个查询,它返回在创建上述主键时自动创建的索引:
SELECT * FROM sys.indexes WHERE name = ‘PK__Colors__8DA7674DD34F4585’;
结果(使用垂直输出):
object_id | 885578193 name | PK__Colors__8DA7674DD34F4585 index_id | 1 type | 1 type_desc | CLUSTERED is_unique | 1 data_space_id | 1 ignore_dup_key | 0 is_primary_key | 1 is_unique_constraint | 0 fill_factor | 0 is_padded | 0 is_disabled | 0 is_hypothetical | 0 is_ignored_in_optimization | 0 allow_row_locks | 1 allow_page_locks | 1 has_filter | 0 filter_definition | NULL compression_delay | NULL suppress_dup_key_messages | 0 auto_created | 0
在本例中,我将结果缩小到仅包含与我刚刚创建的主键同名的行。如果需要返回更多结果,则始终可以删除该子句。WHERE
我们可以看到,这个索引有一个 .type_descCLUSTERED
示例 4 – 命名主键
我们在上面创建的主键由系统自动命名。如果您愿意,可以提供自己的姓名。
下面是指定主键名称的示例。在本例中,我还指定了一个非聚集索引。
USE PK_Test;
CREATE TABLE Cats ( CatId int IDENTITY (1,1) NOT NULL, CONSTRAINT PK_Cats_CatId PRIMARY KEY NONCLUSTERED (CatId), CatName varchar(50) );
在这个示例中,我使用 optional 关键字来指示主键定义的开始,后跟我为主键选择的名称。我还使用该关键字来指定非聚集索引。CONSTRAINT``NONCLUSTERED
检查主键:
SELECT name, type, unique_index_id, is_system_named FROM sys.key_constraints WHERE type = ‘PK’;
输出:
+------------------------------+--------+-------------------+-------------------+
| name | type | unique_index_id | is_system_named |
|------------------------------+--------+-------------------+-------------------|
| PK__Colors__8DA7674DD34F4585 | PK | 1 | 1 |
| PK_Cats_CatId | PK | 2 | 0 |
+------------------------------+--------+-------------------+-------------------+检查索引:
SELECT * FROM sys.indexes WHERE name = ‘PK_Cats_CatId’;
结果(使用垂直输出):
object_id | 917578307 name | PK_Cats_CatId index_id | 2 type | 2 type_desc | NONCLUSTERED is_unique | 1 data_space_id | 1 ignore_dup_key | 0 is_primary_key | 1 is_unique_constraint | 0 fill_factor | 0 is_padded | 0 is_disabled | 0 is_hypothetical | 0 is_ignored_in_optimization | 0 allow_row_locks | 1 allow_page_locks | 1 has_filter | 0 filter_definition | NULL compression_delay | NULL suppress_dup_key_messages | 0 auto_created | 0
所以我们可以看到这次是.type_descNONCLUSTERED
请注意,创建表时,只能为一个约束指定。如果为约束指定了约束,并且还指定了约束,则默认为 .CLUSTERED``UNIQUE``PRIMARY KEY``PRIMARY KEY``NONCLUSTERED
示例 5 – 在可为空的列上创建主键
只能为定义为 的列创建主键。如果尝试在设置为 的列上创建主键,则会收到错误。NOT NULL``NULL
但是,如果未指定可空性,则默认情况下会将列设置为 。NOT NULL
为了演示这一点,让我们创建另一个表,但这一次,我们将它设置为 :NULL
USE PK_Test;
CREATE TABLE Dogs ( DogId int IDENTITY (1,1) NULL PRIMARY KEY, DogName varchar(50) );
输出:
Msg 8147, Level 16, State 1, Line 3
Could not create IDENTITY attribute on nullable column 'DogId', table 'Dogs'.
Msg 8111, Level 16, State 1, Line 3
Cannot define PRIMARY KEY constraint on nullable column in table 'Dogs'.
Msg 1750, Level 16, State 0, Line 3
Could not create constraint or index. See previous errors.正如预期的那样,我们收到一个错误。
让我们从表定义中删除,然后重试:NULL
USE PK_Test;
CREATE TABLE Dogs ( DogId int IDENTITY (1,1) PRIMARY KEY, DogName varchar(50) );
输出:
Commands completed successfully.
Total execution time: 00:00:00.015这次表创建成功。
我们来看看:
SELECT t.name AS ‘Table’, c.name AS ‘Column’, c.is_nullable, c.is_identity FROM sys.columns c INNER JOIN sys.tables T ON c.object_id = t.object_id WHERE c.name = ‘DogId’;
输出:
+---------+----------+---------------+---------------+
| Table | Column | is_nullable | is_identity |
|---------+----------+---------------+---------------|
| Dogs | DogId | 0 | 1 |
+---------+----------+---------------+---------------+因此,我们可以看到它不可为空,因为该标志设置为 .is_nullable0
示例 6 – 多列上的主键
您还可以在多个列上创建主键。多列主键也称为复合主键。若要创建复合主键,只需在定义键时用逗号分隔列。
示例如下:
CONSTRAINT PK_Name PRIMARY KEY (Column1, Column2)
下面是可以使用多列主键的情况示例:
CREATE TABLE Musician ( MusicianId int NOT NULL, FirstName varchar(60), LastName varchar(60), CONSTRAINT PK_Musician PRIMARY KEY (MusicianID) );
CREATE TABLE Band ( BandId int NOT NULL, BandName varchar(255), CONSTRAINT PK_Band PRIMARY KEY (BandId) );
CREATE TABLE BandMember ( MusicianId int NOT NULL, BandId int NOT NULL, CONSTRAINT PK_BandMember PRIMARY KEY (MusicianID, BandId), CONSTRAINT FK_BandMember_Band FOREIGN KEY (BandId) REFERENCES Band(BandId), CONSTRAINT FK_BandMember_Musician FOREIGN KEY (MusicianId) REFERENCES Musician(MusicianId) );
在此示例中,表具有多列主键。在这种情况下,主键中的每一列也是另一个表的主键的外键,但这不是必需的。BandMember
有关此示例的更详细说明,请参阅如何在 SQL Server 中创建复合主键。
另请参阅如何在 SQL Server 中创建复合外键,了解引用上述复合主键的多列外键更进一步的示例。