主键和身份(Identity)有什么区别?

87
在 SQL Server 数据库中,主键和自增列的区别是什么?一列可以成为主键而不是自增列,但是一列不能成为自增列而不是主键。
除了这些区别,主键和自增列相比只有主键列提供什么?
7个回答

107

一列可以成为标识列而不是主键。

标识列仅是自动增长的列。

主键是唯一定义行的列或多列组合。

这两者经常一起使用,但并非必须如此。


1
实际上,我相信SQL Server确实需要它们是这样的,但其他数据库可能不需要。 - Erik Funkenbusch
12
我99%确定它不会,但没有实例可确认。 - Joe
1
然后粘贴到错误的创建表中。这个可以使用非自增列作为主键...
创建表pktest(nonpk int identity(1,1),pk int primary key not null)
- KenJ
3
+1 好的答案。PK 不需要是自动递增的数字,但对于每个条目,它必须是唯一的值。如果要使用非标识符的 PK,则可能需要首先检查已存在于表中的任何新标识与那些已存在的标识是否相同。 - Evan Plaice
2
SQL Server会比我们编写的任何重复项检查更快地拒绝主键的重复输入。我们在代码中处理拒绝,因此实际上我们已经检查了重复输入。 - RC_Cleland

18

本回答不是关于“什么是身份和主键”,而是更多地讲述为什么需要使用它们,因为Joe在上面已经正确回答了“什么是”问题。

身份是SQL控制的一个值。Identity是一个行功能。在SQL Server中,它是顺序的,增加或减少值。它应该永远不被修改,并且应忽略价值中的间隙。链接表B到表A中非常有用,因为该值永远不会重复。在每种情况下,身份都不是聚集索引的最佳选择。如果一张表包含审计数据,则以发生日期创建聚集索引可能更好,因为记录的日期在数据页面中是顺序的,这样将使得回答“今天到四天前发生了什么”这个问题变得更容易。

主键使行中的列成为唯一的。主键是列函数。任何表上只能定义一个主键,但可以创建多个唯一索引来模拟主键。并不总是将主键聚集。考虑电话簿。如果按主键(电话号码)聚集电话簿,则返回“First Street”上的电话号码的查询将非常昂贵。

我遵循的身份和主键的一般规则如下:

  1. 始终使用身份列
  2. 在用于范围查找的列或列上创建聚集索引
  3. 保持聚集索引狭窄,因为聚集索引将添加到所有其他索引的末尾
  4. 创建主键和唯一索引以拒绝重复值
  5. 较窄的键更好
  6. 为每个参与连接的列创建索引

这些是我遵循的一般规则。


2
您提到标识值从不重复。但如果手动插入或重新设置(https://subhrosaha.wordpress.com/2012/11/14/sql-server-duplicate-values-in-identity-columns/)它们可能会重复。如果您想保证唯一性约束,例如必须向列添加唯一索引。 - broadband

10

主键(也称为候选键)是具有唯一性和最小化属性的任何属性集。这意味着关键列或列被限制为唯一。换句话说,DBMS不允许任何两行在那些属性上具有相同的值。

IDENTITY属性有效地为列创建了一个自动递增的默认值。该列不必是唯一的,因此IDENTITY列不一定是一个键。

然而,IDENTITY列通常打算用作键,因此它通常有一个唯一性约束条件,以确保不允许重复项。


7
在这种情况下,"Identity"这个词似乎有点不确切,因为正如你所指出的和其他人也提到的一样,它并不总是唯一的。你的回答帮助那些更熟悉MySQL的人更好地理解SQL Server的Identity属性,强调它只是为列创建一个自动递增的默认值,因此看起来类似于MySQL的AUTO_INCREMENT属性。谢谢。 - Jason Frank

2

主键列和自增列的主要区别:

主键列:

  • 主键不能有重复值。
  • 它会为表创建聚集索引。
  • 可以为任何列类型设置主键。
  • 在插入表时需要提供主键列的值。

自增列:

  • 自增列可以有重复值。
  • 只能为整数相关的列(如int、bigint、smallint、tinyint或decimal)设置。
  • 无需插入自增列的值。它是基于种子自动插入的。

1

根据反馈所做的修改

一个键是唯一的,用于标识一行。它是一种识别行的方式。行可能没有、有一个或多个键。这些键可以由一个或多个列组成。

键是带有唯一约束条件的索引。这使它们与非键索引区分开来。

任何具有多列的索引都称为“复合索引”。

传统上,主键被视为唯一标识行的主要键。只能有一个主键。

根据表的设计,可能没有主键。

主键就是那个“主键”。它是指定行的唯一标识的主要键。根据表的设计,这可能是一个误称,多个键表达了唯一性。

在SQL Server中,主键可以是聚集的。这意味着剩余的列附加到该键的索引叶级别上。换句话说,一旦SQL Server找到了键,它也找到了行(需要明确的是,这是因为聚集方面)。

自增列只是一种为行生成唯一ID的方法。

这两者经常一起使用,但并非必须的。


1
SQL Server 不要求主键必须是聚集索引。 - RC_Cleland
1
@IanC: "Primary" 的原因是这是唯一标识行的关键字。但这并不是真正的解释,因为任何关键字或超级关键字都可以唯一标识一行,而不仅仅是“主”关键字。 "Primary" 实际上只是指“首选”或“特殊”的关键字 - 尽管它只有你想让它变得特殊时才会如此。 - nvogel
1
@IanC:危险在于,通过这种描述方式,一个不了解情况的人可能会认为表中只能或应该有一个这样的键,这显然是不正确的。 - nvogel
1
@IanC:因为物品通常有多个标识符,并且不同的数据库用户有时需要不同的键(例如,开发人员通常与终端用户使用不同的键)。原则上,所有候选键都可以承担相同的功能。因此,说我们只能或必须只有一个主键,或者主键在任何基本方式上都是特殊的,这样的说法并没有特别意义。 - nvogel
1
“Keys are indexes”这个评论是一个经典的错误,但如果它被理解为“在SQL Server中,键总是通过索引实现”的意思,那么我想这个错误还算可以原谅。我不确定为什么你现在想说行而不是表具有键。无论如何,我认为进一步细化它并不值得。任何想要这种详细信息的人都应该去好书中查找。 - nvogel
显示剩余12条评论

1

您不仅可以将IDENTITY与整数一起使用,还可以将其与任何具有0比例的数字数据类型一起使用。

主键可以具有比例,但不是必需的。

IDENTITY与PRIMARY KEY或UNIQUE约束结合使用,可提供简单的唯一行标识符。


0
主键强调在同一列上所有记录的唯一性和避免重复值,而标识提供在一个列中增加数字而不插入数据。这两个特性可以应用于单个列或不同的列。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接