Database design 复合主键的使用

Database design 复合主键的使用,database-design,Database Design,假设我有一个表,我想在其中记录用户名。该表至少应有两列:UserID和Name。通常我会看到人们在UserID上设置主键,然后启用自动递增并称之为“一天” 然而,这似乎不对,键不应该是两列之间的复合键吗?因为我们不希望用户名被重复。我们还希望保留UserID,这样,如果某个用户的名称发生更改,我们就不会中断对该用户的现有引用 我想说的是,似乎许多人默认为他们创建的每个表使用带有PK的ID列,而不确保键也强制其他列具有唯一性 话虽如此,我说一个表应该始终有一个ID列用于引用,但使用复合主键同样重要

假设我有一个表,我想在其中记录用户名。该表至少应有两列:
UserID
Name
。通常我会看到人们在
UserID
上设置主键,然后启用自动递增并称之为“一天”

然而,这似乎不对,键不应该是两列之间的复合键吗?因为我们不希望用户名被重复。我们还希望保留
UserID
,这样,如果某个用户的名称发生更改,我们就不会中断对该用户的现有引用

我想说的是,似乎许多人默认为他们创建的每个表使用带有PK的ID列,而不确保键也强制其他列具有唯一性


话虽如此,我说一个表应该始终有一个ID列用于引用,但使用复合主键同样重要,对吗?

不,您不希望它作为复合键;这意味着组合是主键,因此可以在同一ID上有不同的名称,在同一名称上有不同的ID

即:

在没有任何其他约束的情况下,使主键成为
(UserID,Name)
的组合将使以前的数据完全合法


您的
UserID
列是一个代理键;关于使用代理键与自然键(您的
Name
列是一个自然候选键)是否明智的讨论我将留待下次讨论,但是如果您想保持现在的设计方式,那么您应该将
UserID
作为主键,但还要在
Name
上添加一个唯一的约束。这将防止将相同的名称附加到多个记录。

如果希望名称是唯一的,请对此设置单独的约束。这是另一个问题。你的钥匙是两者的结合没有好处,只有缺点。这意味着用户名和名称都可以重复。这是你想要的吗

主键不仅仅用于唯一性。它还可以极大地提高索引性能。通常你认为你的自然钥匙会是独一无二的,但这会在以后改变。不过,自然关键点可能是一个很好的移动方式。另一个合理的选择是使用guid。为您的主键


有很多关于多栏键的好信息,以及多栏键的优点。许多人(包括我)相信自动编号通常是最好的,尽管有。当然,您应该了解这些因素,并最终在不同的情况下使用不同的策略。

您应该将UserID和Name都设置为键,这与设置复合键不同(复合键意味着一个键,而不是两个键)

您是对的,有些人会天真或不小心地只为表分配一个代理键,而不必考虑需要什么样的自然键。至少你可以从许多人那里得到这样的印象,他们主张代理是自然钥匙的“更好”替代品。很明显,他们不是那种人。代孕者是没有选择的,因为他们实现了完全不同的事情


重要的是,一个表应该具有数据完整性所需的尽可能多的键,以确保该表准确地表示它要表示的业务规则。永远不要被误导,以为一个键永远是您所需要的。

对于名称字段,它应该是唯一的索引还是唯一的键?@Nick:我假设您使用的是SQL Server。这两种方法都可以实现唯一性,但使用唯一键也可以(如果您以后想这样做的话)在其他表中使用这两个列作为外键。非常擅长这两种方法的人肯定有不同的意见(re:natural vs.surrogate)。需要注意的是:使用GUID作为主键时,使用
newsequentialid()
而不仅仅是
newid()
,这一点很重要,否则代理键提供的唯一真正性能优势(由于所有值都是连续的,因此没有页面分割/移动而导致插入性能)就消失了。dportas说“代理根本不是替代品,因为它们实现了完全不同的事情。”我同意。在没有任何其他约束的情况下,代理id号标识行,但不标识实体。标识行很容易;标识实体有时不容易。
UserID    Name
-----------------
1         BobaFett
2         JarJar
1         JarJar
2         BobaFett