首页 文章

主键与唯一约束?

提问于
浏览
44

我目前正在设计一个全新的数据库 . 在学校里,我们总是学会在每张 table 上放一把主键 .

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

你的观点是什么?

16 回答

  • 0

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

    但我不在我的SQL中使用PK列 . 这是出于管理目的,比如删除一些错误的行,如果设置为AUTO INCREMENT,则找出PK值之间的间隙 . 并且,它使将PK作为数字而不是一组列或char数组的意义 .

  • 0

    我已经写了很多关于这个主题的文章:如果你读过我的任何内容,请注意我可能特指Jet a.k.a. MS Access .

    在Jet中,使用非维护的聚簇索引(在紧凑状态下聚集)在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约束,希望他们能更好地考虑所有候选键,特别是当他们选择使用“autonumber”列时(应该)在数据模型中没有意义 . 但我宁愿民间选择一个考虑周全的关键并使用PRIMARY KEY而不是将其放在自动增量专栏中 .

    所有 table 都应该有PK吗?我说是的,因为否则意味着你至少错过了引擎提供PK的一点点优势,最糟糕的是你没有数据完整性 .

    BTW Chris OC在这里提出了关于时态表的一个很好的观点,它需要有序的主键(小写),这些主键不能通过简单的PRIMARY KEY约束(大写的SQL关键字)来实现 .

  • 38

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

    我认为没有理由改变尝试过的方法 . 毕竟,主键是关系数据库的基本设计功能 .

    使用UNIQUE来达到同样的目的听起来真的很惹我生气 . 他们的理由是什么?

    编辑:我的注意力刚刚回到这个旧答案 . 也许你所读到的关于PK与UNIQUE的讨论涉及人们制造某种PK的唯一目的是为了强制执行它的唯一性 . 对此的答案是,如果它是一个键,那么将其设为键,否则使其成为独特的 .

  • 2

    PRIMARY KEY

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

    UNIQUE KEY

    1. Null 允许空值 . 但只有一个Null值 . 2. INDEX 默认情况下,它会添加UNIQUE非聚集索引 . 3. LIMIT 一个表可以有多个UNIQUE键列[s] .

  • 5

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

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

  • 3

    主键实际上只是一个不允许NULL的candidate key . 因此,在SQL术语中 - 它与任何其他唯一键没有区别 .

    然而,对于我们的非理论性RDBMS来说,从来没有听过它的论点 . 如果该主键是surrogate key,那么您应该对natural key(s)具有唯一约束 .

    离开的重要一点是,你应该对所有候选(无论是自然的还是代理的)键有唯一的约束 . 然后,您应该选择Foreign Key中最容易引用的那个作为您的主键* .

    你还应该有一个clustered index * . 这可能是您的主键,或自然键 - 但它不是必须的 . 您应该根据表的查询用法选择聚簇索引 . 如果有疑问,主键不是一个糟糕的首选 .

    • 虽然它接受了标准做法,但却非常支持主键 . 事实上,如果某些RDBMS只允许主键引用,我不会感到惊讶 .

    • 编辑:_1451850_的"clustered table"和"clustered index"的术语与Sql Server不同 . 相当于我在Oracle-ese中所说的是Index Ordered Table,建议用于OLTP表 - 我认为这是SO问题的主要焦点 . 我假设如果您负责大型OLAP数据仓库,那么您应该对数据库设计和优化有自己的看法 .

  • 1

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

    我希望那些反对他们的人认为没有理由以不同的方式对待一个密钥 . 这就是我的立场 .

    [编辑]显然,即使我自己的答案没有50分,我也无法发表评论 .

    @chris:我没有伤害任何伤害 . "Primary Key"真的只是语法糖 . 我一直都在使用它们,但我当然不需要 . 需要一个唯一的密钥,是的,但不一定是主密钥 .

  • 3

    非常罕见的非规范化会让你想要一个没有主键的表 . 主键仅根据PK的性质自动具有唯一约束 .

    如果要保证ADDITION中列的唯一性,则可以使用唯一约束 .

    总是有PK的规则是好的 .

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

  • 10

    你应该 always 有一个主键 .

    但是,我怀疑你的问题只是措辞有点误导,你实际上是要问主键是否应该始终是一个自动生成的数字(也称为代理键),或者某个唯一字段是实际有意义的数据(也称为自然关键),像人的SSN,书籍的ISBN等 .

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

    我的看法是,如果自然键确实是唯一的并且永远不会改变,那么它们更可取 . 但是,你应该小心,即使看起来像SSN可能会在某些情况下改变SSN的东西 .

  • 46

    在您将从此表与将引用此值的其他表 Build 关系的情况下,应使用主键 . 但是,根据表的性质和您考虑应用唯一约束的数据,您可以将该特定字段用作自然主键,而不必 Build 代理键 . 当然,代理与自然键是另一个完整的讨论 . :)

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

  • 1

    除非表是在您处理数据时暂存数据的临时表,否则您总是希望在表上放置主键,这就是原因:

    1 - 唯一约束可以允许空值,但主键永远不允许空值 . 如果在具有空值的列上运行具有连接的查询,则从结果数据集中消除这些行,因为null不等于null . 这就是大公司甚至可以犯会计错误并重新获利的方式 . 他们的查询没有显示应该包含在总数中的某些行,因为在其唯一索引的某些列中存在空值 . 应该使用主键 .

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

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

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

  • 9

    我们需要在逻辑结构和物理结构之间进行区分,并在理论和实践之间进行类似区分 .

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

    在物理层面,大多数RDBMS将主键约束实现为唯一索引 . 如果您选择的RDBMS就是其中之一,那么在将列指定为主键并简单地在列上添加唯一约束之间可能没有太大的实际区别 . 但是:其中一个选项可以捕获您的意图,而另一个选项则不会 . 所以,这个决定是明智之举 .

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

    任何告诉你使用Unique Constraints而不是Primary Keys作为一般规则的人应该提供一个非常好的理由 .

  • 1

    问题是主键可以是一个或多个唯一标识表的单个记录的列,其中唯一约束只是对字段的约束,该字段仅允许表中任何给定数据元素的单个实例 .

    个人而言,我使用GUID或自动递增BIGINTS(SQL SERVER的标识插入)用于在我的表中进行交叉引用的唯一键 . 然后我将使用其他数据来允许用户选择特定记录 .

    例如,我将拥有一个员工列表,并在我在幕后使用的每条记录上附加一个GUID,但是当用户选择一个员工时,他们会根据以下字段选择它们:LastName FirstName EmployeeNumber .

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

  • 1

    帖子说最好使用唯一约束(也就是某些数据库的唯一索引)而不是PK

    我想这里唯一的一点是旧的讨论“自然与代理键”,因为唯一索引和pk是相同的 .

    翻译:

    帖子说最好使用自然键而不是代理键

  • 1

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

    编辑添加:现实世界数据通常没有真正保证规范化表结构中唯一性的自然键也是一个真正的问题,特别是如果数据库是以人为中心的话 . 姓名,甚至姓名,地址和电话号码相结合(想想父亲和儿子在同一医疗实践中)不一定是唯一的 .

  • 0

    我正在考虑这个问题 . 如果你使用独特的,你会伤害2. NF . 根据这一点,每个非pk属性必须依赖于PK . 这个唯一约束中的这对属性将被视为该属性的一部分PK .

    很遗憾7年后回复,但不想开始新的讨论 .

相关问题