主键与唯一约束?

问题描述:

我目前正在设计一个全新的数据库。在学校里,我们总是学会在每张桌子上放一个主键。主键与唯一约束?

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

你的观点是什么?

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

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

使用UNIQUE来达到相同的目的听起来真的很讨厌我。他们的理由是什么?

编辑:我的注意力刚刚回到这个旧的答案。也许你读到的关于PK和UNIQUE的讨论涉及到人们为了强制唯一性而做一些PK。对此的答案是,如果它是一个关键字,那么将其设为关键字,否则将其设为唯一。

+1

你说,如果它是一个关键,使它成为一个关键,如果它是唯一的,使其独特。但是,真的,什么使钥匙成为钥匙而不是唯一的钥匙?你对*键的定义是什么? – Pacerier 2013-11-22 21:38:04

+0

@Prier假设我们有一个学生信息数据库。在这个数据库中,学生用主键StudentNumber标识。 在学生表中,我们保留诸如SSN/SIN或其他区域等价物。作为密钥错误检查的一部分,我们希望这个字段是唯一的。但这不是关键领域。 (尽管可能,假设StuID和SSN之间的1:1对应关系) 房间分配也可以是唯一的,但不是关键。 (虽然我更倾向于将学生分配到一个房间,而不是一个房间给学生) – 2013-11-28 13:48:21

+0

在你的例子中,为什么不把SSN/SIN作为钥匙? – Pacerier 2013-11-30 03:52:44

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

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

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

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

主键应该在那里你会被从该表建立关系,以将引用这个值其它表的情况下使用。但是,根据表格的性质以及您正在考虑应用唯一约束的数据,您可能可以将该特定字段用作自然主键,而不必建立替代键。当然,代理与自然键是一个完整的其他讨论。 :)

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

问题是主键可以是一个或多个列,它唯一地标识一个表的单个记录,其中唯一约束只是一个字段上的约束,它只允许任何给定数据元素的单个实例一张桌子。个人而言,我使用GUID或自动递增BIGINTS(用于SQL SERVER的身份插入)作为我的表中用于交叉引用的唯一键。然后我会使用其他数据来允许用户选择特定的记录。

例如,我将列出雇员名单,并在每个记录后附加GUID,但是当用户选择一名雇员时,他们会根据以下字段选择他们:姓氏+名字+员工号码。

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

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

我认为那些反对他们的人认为没有理由对待一个关键字而不是另一个。这就是我的立场。

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

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

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

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

主键实际上只是一个candidate key,它不允许NULL。因此,用SQL语言来说 - 它与其他任何唯一密钥没有区别。

但是,对于我们的非理论型关系数据库管理系统,您应该有一个主键 - 我从来没有听说过其他方面的争论。如果该主键是surrogate key,那么您应该natural key(s)有唯一的限制。

重要的一点是你应该对全部这个候选人(不管是自然的还是代理的)密钥有独特的限制。然后你应该选择一个Foreign Key中最容易引用的主键*。您还应该有一个clustered index *。这可能是你的主键,或者一个自然键 - 但它不是必需的。您应该根据表的查询使用情况选择聚集索引。如果有疑问,主键不是不好的首选。

  • 虽然它在技术上只需要参考的唯一键的外键关系,它是公认的标准做法,以大大青睐的主键。事实上,如果某些RDBMS只允许主键引用,我不会感到惊讶。

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

除非该表是一个临时表,而你在这工作阶段的数据,你总是希望把上表的主键和这里的原因:

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

2 - 唯一索引将自动放置在主键上,因此您不必创建一个索引。

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

4 - 很多前端开发环境需要主键才能更新表或进行删除。

我们需要在这里区分逻辑结构和物理结构,理论和实践之间也是类似的。

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

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

此外,如果主键已正确标记(例如图表和半自动外键约束支持),则某些RDBMS可提供其他功能。

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

帖子说这是更好地使用唯一约束(对于某些分贝又名唯一索引),而不是PK

我想,这里的唯一的一点是相同的旧讨论“自然VS代理键” ,因为独特的索引和PK是同一回事。

翻译:

帖子说这是更好地使用自然键而不是替代键

你应该总是主键。

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

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

我的看法是,如果自然键确实是唯一的并且永远不会改变,那么它更可取。但是,您应该小心,即使在某些情况下,SSN等人可能会发生变化,但表面上看起来很稳定。

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

编辑补充:这也是一个现实的问题是现实世界的数据往往不具有真正保证了标准化的表结构的独特性,特别是在数据库为以人为本的自然键。姓名,甚至是姓名,地址和电话号码(认为父子在同一医疗实践中)并不一定是唯一的。

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

但我并不在我的sql语句使用PK列。这是为了管理目的,如删除一些错误的行,找到PK值之间的差距,如果它设置为自动增量。而且,将PK作为数字是有意义的,而不是一组列或字符数组。

我已经写了很多关于这个问题:如果你看过我的任何明确的是,我可能特指喷气又称MS访问。

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

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

不管你的SQL引擎,PRIMARY KEY的选择是任意的,发动机比。通常发动机会对PK有特殊的意义,因此你应该知道它是什么,并将它用于你的优势。我鼓励人们使用NOT NULL UNIQUE约束,希望他们能够更好地考虑所有候选键,特别是当他们选择使用'自动编号'列(在数据模型中应该没有意义)时。但是我宁愿选择一个考虑得很好的密钥,并使用PRIMARY KEY而不是放在自习增量栏中。

是否所有表都有PK?我说是的,因为这样做意味着至少你错过了引擎提供PK的轻微优势,最坏的情况是你没有数据完整性。

BTW克里斯OC使得一个好点约在这里无法通过简单的PRIMARY KEY约束(SQL关键字用大写)来实现的时态表,这需要测序主键(小写)。

我在想我的这个问题。如果你使用独特的,你会伤害2. NF。据此,每个非pk属性必须取决于PK。这个唯一约束中的这对属性将被视为PK的一部分。

对不起回复这款7年后的今天,但没有要开始新的讨论。

PRIMARY KEY

1.空 它不允许Null值。因此,我们参考PRIMARY KEY = UNIQUE KEY + NOT NULL CONSTRAINT。 2. INDEX 默认情况下,它增加了一个聚集索引。 3. LIMIT 甲表只能有一个主键列[s]的。

UNIQUE KEY

1.空 允许空值。但只有一个空值。 2. INDEX 默认情况下,它增加了一个独特的非聚集索引。 3. LIMIT 一个表可以具有多于一个的唯一键列[s]的。