有两个概念很接近,但不应混淆:IDENTITY
和PRIMARY KEY
每个表(除了罕见的情况)都应该有一个PRIMARY KEY
,这是唯一标识一行的一个值或一组值.
请参阅here了解原因.
IDENTITY
是SQL Server
中某列的属性,这意味着该列将自动填充递增值.
由于此属性的性质,此列的值本质上是UNIQUE
.
然而,在IDENTITY
列上不会自动创建UNIQUE
约束或UNIQUE
索引,并且在发出SET IDENTITY_INSERT ON
之后,可以在IDENTITY
列中插入重复的值,除非它受到明确的UNIQUE
约束.
IDENTITY
列不一定是PRIMARY KEY
,但通常用于填充替代项PRIMARY KEY
在任何特定情况下,它可能有用,也可能无用.
因此,你的问题的答案是:
问题是:数据库中的每个表都应该有一个用作PK的标识字段吗?
这是:
No. There are cases when a database table should NOT have an IDENTITY
field as a PRIMARY KEY
.
在我脑海中出现了三种情况,当IDENTITY
作为PRIMARY KEY
不是最好的主意时:
- 如果你的
PRIMARY KEY
是复合的(比如在多对多链接表中)
- 如果你的
PRIMARY KEY
是自然的(比如州代码)
- 如果
PRIMARY KEY
在数据库中是唯一的(在本例中,使用GUID
/UUID
/NEWID
)
所有这些情况都意味着以下情况:
You shouldn't have IDENTITY
when you care for the values of your PRIMARY KEY
and explicitly insert them into your table.
Update:
多对多链接表与它们链接的表之间应该有一对id
,作为复合键.
这是一个自然的复合密钥,您已经必须使用它(并设置为UNIQUE
),因此没有必要为此生成代理密钥.
我不明白你为什么要从任何其他表中引用一个many-to-many
链接的表,除了它们链接的表,但是假设你有这样的需求.
在这种情况下,只需通过复合键引用链接表.
此查询:
CREATE TABLE a (id, data)
CREATE TABLE b (id, data)
CREATE TABLE ab (a_id, b_id, PRIMARY KEY (a_id, b_id))
CREATE TABLE business_rule (id, a_id, b_id, FOREIGN KEY (a_id, b_id) REFERENCES ab)
SELECT *
FROM business_rule br
JOIN a
ON a.id = br.a_id
比这个更有效:
CREATE TABLE a (id, data)
CREATE TABLE b (id, data)
CREATE TABLE ab (id, a_id, b_id, PRIMARY KEY (id), UNIQUE KEY (a_id, b_id))
CREATE TABLE business_rule (id, ab_id, FOREIGN KEY (ab_id) REFERENCES ab)
SELECT *
FROM business_rule br
JOIN a_to_b ab
ON br.ab_id = ab.id
JOIN a
ON a.id = ab.a_id
,原因显而易见.