主键与唯一约束?

我目前正在devise一个全新的数据库。 在学校里,我们总是学会在每张桌子上放一个主键。

我读了很多文章/讨论/新闻组的post,说最好是使用唯一的约束(又名一些数据库的唯一索引),而不是PK。

你的观点是什么?

你能提供这些文章的参考?

我看不出有什么理由去改变已经尝试过的方法。 毕竟,主键是关系数据库的基本devise特征。

使用UNIQUE来达到同样的目的听起来真的令人讨厌。 他们的理由是什么?

编辑:我的注意力刚刚回到这个旧的答案。 也许你所读到的关于PK和UNIQUE的讨论是为了强化唯一性的唯一目的,而把人们做成PK。 答案是,如果它是一个关键,那么把它作为关键,否则使它唯一。

主键实际上只是一个不允许NULL的候选键 。 就这一点而言,用SQL语言来说,它和其他唯一的密钥没有区别。

但是,对于我们非理论的关系型数据库pipe理系统,你应该有一个主键 – 我从来没有听说过其他方面的争论。 如果这个主键是一个代理键 ,那么你应该对这个自然键有唯一的约束。

重要的一点是你应该对所有的候选人(无论是自然的还是代理人的)都有独特的约束。 你应该select一个最容易引用的外键作为你的主键*。

你也应该有一个聚集索引 *。 这可能是你的主键,或者是一个自然的键 – 但它不是必须的。 您应该根据表的查询使用情况挑选聚集索引。 如果有疑问,主键不是一个不好的首选。

  • 虽然在技术上只需要在外键关系中提及一个唯一的键,但是大家都非常喜欢这个主键的标准做法。 事实上,如果某些RDBMS只允许主键引用,我不会感到惊讶。

  • 编辑:有人指出,Oracle的“聚集表”和“聚集索引”的术语不同于Sql Server。 相当于我在Oracle-ese中所说的是一个索引有序表 ,它被推荐用于OLTP表 – 我认为这将是SO问题的主要焦点。 我假设你是否负责一个大的OLAP数据仓库,你应该已经对数据库devise和优化有你自己的意见了。

主键只是一个候选关键字(唯一的约束条件),用于特殊处理(自动创build索引等)。

我希望那些反对他们的人看不出有什么理由把另一个关键字对待。 那就是我的立场。

[编辑]显然我不能评论,即使我自己的答案没有50分。

@chris:我不认为有任何伤害。 “主键”实际上只是句法糖。 我一直使用它们,但我当然不认为它们是必需的。 需要唯一的密钥 ,是的,但不一定是主密钥。

这将是非常罕见的非规范化,这将使你想有一个没有主键的表。 主键具有唯一的约束,就像PK一样。

当你想保证在主键的附加列中的唯一性时,将使用唯一的约束。

总是有一个PK的规则是一个很好的规则。

http://msdn.microsoft.com/en-us/library/ms191166.aspx

你应该总是有一个主键。

不过,我怀疑你的问题只是措辞有点误导,你实际上是要问,如果主键应始终是一个自动生成的数字(也称为代理键),或一些独特的字段是实际有意义的数据(也称为自然关键字),如人民的SSN,书籍的ISBN等等。

这个问题在DB领域是一个古老的宗教战争。

我的看法是,如果自然钥匙确实是独一无二的,而且永不改变,那么自然钥匙是可取的 但是,你应该小心,即使在某些情况下,像SSN这样的人也可能会改变。

主键应该用在你将build立从这个表到其他表的引用这个值的关系的情况下。 但是,根据表格的性质以及您正在考虑应用唯一约束的数据,您可以将该特定字段用作自然主键,而不必build立替代键。 当然,代理与自然键是另外一个讨论。 🙂

如果此表与其他表之间没有build立关系,则可以使用唯一键。 例如,一个包含有效电子邮件地址列表的表格,在插入新的用户logging或其他types之前,这些表格将与之进行比较。 或者,如果表中具有主键但必须是绝对唯一的值,则可以使用唯一键。 例如,如果您有一个拥有用户名的用户表。 您不希望将用户名称用作主键,但它也必须是唯一的,以便用于login目的。

除非这个表是临时表来处理数据,否则您总是希望在表上放置一个主键,原因如下:

1 – 一个唯一的约束可以允许空值,但是主键不允许空值。 如果使用具有空值的列对联接运行查询,则会从结果数据集中删除这些行,因为null不等于null。 这就是即使大公司可以做出会计错误,并重新获得利润。 他们的查询没有显示应包含在总数中的某些行,因为在其唯一索引的某些列中存在空值。 应该使用主键。

2 – 一个唯一的索引将自动放在主键上,所以你不必创build一个。

3 – 大多数数据库引擎会自动在主键上放置一个聚簇索引,使得查询更快,因为行被连续存储在数据块中。 (如果聚集索引加速查询,可以将聚集索引放在不同的索引上。)如果一个表没有聚集索引,那么这些行将不会连续存储在数据块中,从而使查询由于读/写磁头必须遍历整个磁盘来拾取数据,因此速度较慢。

4 – 很多前端开发环境需要一个主键来更新表或删除。

我们需要在逻辑结构和物理结构之间进行区分,在理论和实践之间也是如此。

首先,从理论的angular度来看,如果你没有主键,你就没有一张表。 就这么简单。 所以,你的问题不是你的表是否应该有一个主键(当然它应该),而是如何在你的RDBMS中标记它。

在物理层面上,大多数RDBMS将主键约束实现为唯一索引。 如果您select的RDBMS是其中之一,那么在将列指定为主键和简单地在该列上设置唯一约束之间可能没有太大的实际区别。 但是:其中一个选项可以捕捉您的意图,而另一个则不会。 所以,这个决定是不容易的。

此外,如果主键被正确标记,如图表和半自动的外键约束支持,一些RDBMS可以提供​​额外的function。

任何告诉你使用唯一约束而不是主键的人都应该提供一个非常好的理由。

主键可以是一个或多个唯一标识一个表的唯一logging的列,其中唯一约束只是一个只允许表中任何给定数据元素的单个实例的字段的约束。

个人而言,我使用GUID或者自动递增BIGINTS(SQL SERVER的标识插入)作为我的表中用于交叉引用的唯一键。 然后我将使用其他数据来允许用户select特定的logging。

例如,我将拥有一个员工列表,并在幕后使用每个logging都附加了一个GUID,但是当用户select一个员工时,他们将根据以下字段select他们:LastName + FirstName +员工号码。

在这种情况下,我的主键是LastName + FirstName + EmployeeNumber,而唯一键是关联的GUID。

post说,最好使用独特的约束(又名一些数据库的唯一索引),而不是PK

我想这里唯一的一点就是老的讨论“自然对代用键”,因为独特的索引和PK是同一回事。

翻译:

职位说,最好使用自然键而不是代理键

我通常使用PK和UNIQUE KEY。 因为即使你没有在模式中表示PK,也总会为你在内部生成一个PK。 对于SQL Server 2005和MySQL 5都是如此。

但是我不使用我的SQL中的PK列。 这是为了pipe理的目的,如删除一些错误的行,findPK值之间的差距,如果它被设置为AUTO INCREMENT。 而且,将PK作为数字是有意义的,而不是一组列或字符数组。

我已经写了很多关于这个问题:如果你读了我的任何东西要清楚,我可能是专门提到Jet又名MS Access。

在Jet中,这些表使用非维护的聚簇索引(紧凑聚簇)在PRIMARY KEY上进行物理sorting。 如果表没有PK,但在NOT NULL列上使用UNIQUE约束定义了候选键,那么引擎将为聚簇索引select一个(如果您的表没有聚簇索引,那么它被称为堆,根本不是一个表!)引擎如何挑选候选键? 它可以select一个包含可空列的列吗? 我真的不知道。 重点是在Jet中,指定引擎的聚集索引的唯一显式方法是使用PRIMARY KEY。 当然在Jet中还有其他用途,例如,如果在SQL DDL中的FOREIGN KEY声明中省略了键,那么它将被用作键,但是为什么不是显式的。

Jet的麻烦在于,大多数创build表的人不了解或不关心聚簇索引。 实际上,大多数用户(我保证)在每个表上放置一个自动增量自动编号列,并且只在该列上定义PRIMARY KEY,而不对自然键和候选键设置任何唯一的约束(自动增量列是否实际上被视为一个关键而不暴露给最终用户本身是另一个讨论)。 这里我不会详细讨论聚集索引,但足以说IMO是一个唯一的自动增量列很less是理想的select。

无论你使用什么SQL引擎,PRIMARY KEY的select都是任意的和引擎特定的。 通常发动机会对PK有特殊的意义,所以你应该知道它是什么,并且把它用在你的优势上。 我鼓励人们使用NOT NULL UNIQUE约束,希望他们能更好地考虑所有的候选键,特别是当他们select使用在数据模型中没有意义的“自动编号”列时。 但是我宁愿select一个考虑好的关键字,而不是使用PRIMARY KEY,而不是把它放在习惯性的自动增长列上。

所有的桌子都应该有PK吗? 我说是的,因为否则意味着至less你错过了一个轻微的优势引擎提供了PK,最坏的情况下,你没有数据的完整性。

顺便说一下,Chris OC在这里提到了一个很好的关于时态表的问题,这些时态表需要按顺序排列的主键(小写字母),不能通过简单的PRIMARY KEY约束(大写的SQL关键字)来实现。

首要的关键

1. Null它不允许空值。 因此,我们引用PRIMARY KEY = UNIQUE KEY + NOT NULL CONSTRAINT。 2. INDEX默认情况下它会添加一个聚集索引。 3.限制一个表只能有一个PRIMARY KEY列[s]。

唯一的关键

1.空允许空值。 但只有一个空值。 2. INDEX默认情况下,它添加一个UNIQUE非聚集索引。 3.限制一个表可以有多个唯一的密钥列[s]。

如果您计划使用LINQ to SQL,如果您计划执行更新,那么您的表将需要主键,如果您计划在断开连接的环境中工作(例如通过WCF服务传递对象),则需要一个timestamp列应用)。

如果你喜欢.NET,PK和FK是你的朋友。

我提交你可能需要两个。 主键本质上需要是唯一的,不能为空。 它们通常是代理键,因为整数创build比字符文件更快的连接,尤其是多字段字符连接。 但是,由于这些通常是自动生成的,所以不能保证数据logging不包括id本身的唯一性。 如果你的表有一个唯一的自然键,你应该有一个唯一的索引,以防止重复的数据input。 这是一个基本的数据完整性要求。

编辑补充说:现实世界中的数据往往没有一个真正的问题,即真正保证了规范化表结构的唯一性,特别是在数据库是以人为中心的情况下。 名字,甚至是姓名,地址和电话号码(认为父子在同一医疗实践中)并不一定是唯一的。

我正在考虑自己的这个问题。 如果你使用独特的,你会伤害2. NF。 据此,每个非PK属性必须依赖于PK。 这个唯一约束中的这对属性被认为是PK的一部分。

对不起,7年后回复,但不想开始新的讨论。