【问题标题】:What is the difference between Primary Key and unique key constraint?主键和唯一键约束有什么区别?
【发布时间】:2010-09-29 09:13:33
【问题描述】:

Primary keyunique Key constraint有什么区别?

它有什么用??

【问题讨论】:

  • 你问的是key和constraint(PK和unique约束)的区别还是PK约束和UK约束?

标签: sql-server sql-server-2005 database-design primary-key


【解决方案1】:

两者都用于表示表格的candidate keys

您只能有一个表的主键,因此如果您有多个候选者,则只需选择一个。

两者都可以用于外键约束。在 SQL Server 中,主键列不能为空。 Unique Key 约束中使用的列可以。

默认情况下,在 SQL Server 中,如果在堆上创建主键,则主键将成为聚集索引,但 PK 和聚集索引必须相同,这绝不是强制性的。

【讨论】:

  • “默认情况下,在 SQL Server 中,如果在堆上创建主键,它将成为聚集索引”是什么意思?
  • @vgv8 - 堆是没有聚集索引的表。如果您在堆上运行ALTER TABLE dbo.tbl ADD CONSTRAINT PKNAME PRIMARY KEY (foo) ,它将创建一个聚集索引,索引的键是PK 列。如果表已经有聚集索引,它将创建一个非聚集唯一索引。
  • 啊,这样说会更容易理解,聚集索引只能是表上的一个,如果在创建 PK 时还没有聚集索引,则创建 PK 聚集(使表集群的,非堆的),否则 PK 是非集群的。您的回答含糊不清,因为索引,集群或非集群,总是(创建)在 B 树中,如果该数据是非集群的,实际的表数据可能在堆上。我理解错了吗?
【解决方案2】:

主键是用于识别相关行的键。除此之外,它可能还有一些意义(如果已经有一块“真实”数据可以提供服务)或者它可能纯粹是一个实现人工制品(大多数 IDENTITY 列,以及其他数据库系统上等效的自动递增值) .

唯一键是更一般的情况,其中键不能有重复值。在大多数情况下,人们不能在同一司法管辖区拥有相同的社会安全号码(国际案例可能会有所不同)。因此,如果我们存储社会安全号码,那么我们希望将它们建模为唯一的,因为它们与现有号码匹配的任何情况显然是错误的。用户名通常也必须是唯一的,所以这是另一种情况。外部标识符(另一个系统、标准或协议使用的标识符)也往往是唯一的,例如只有一种语言具有给定的 ISO 639 代码,因此如果我们存储 ISO 639 代码,我们会将其建模为唯一的。

这种唯一性也可以跨越多个列。例如,在大多数分层分类系统(例如文件夹结构)中,任何项目都不能同时具有相同的父项和相同的名称,尽管可能存在具有相同父项和不同名称的其他项,以及具有相同名称和不同名称的其他项父母。这种多列功能也存在于主键上。

一张表也可能有多个唯一键。例如。一个用户可能同时拥有一个 ID 号和一个用户名,并且两者都需要是唯一的。

因此,任何不可为空的唯一键都可以用作主键。有时来自被建模的固有数据的主键被称为“自然主键”,因为它们是数据的“自然”部分,而不仅仅是实现工件。使用哪个决定取决于以下几点:

  1. 规格变更的可能性。如果我们将社会安全号码建模为唯一性,然后必须适应多个司法管辖区,其中两个或多个使用足够相似的编号系统以允许冲突,我们可能只需要删除唯一性约束(其他更改可能 需要)。如果它是我们的主键,我们现在还需要使用一个新的主键,并更改使用该主键作为关系一部分的任何表,以及加入它的任何查询。

  2. 查找速度。关键效率可能很重要,因为它们用于许多 WHERE 子句和(更经常)许多 JOINs 中。尤其是JOINS,查找速度至关重要。影响将取决于实现细节,不同的数据库会根据它们处理不同数据类型的方式而有所不同(从性能的角度来看,在 Postgres 中使用大段文本作为主键时,我几乎没有疑虑,我可以指定使用哈希连接,但我会非常犹豫在 SQLServer 中这样做 [编辑:对于“大”,我考虑的可能是用户名的大小,而不是整个 Norse Eddas 的大小!])。

  3. 键的频率是唯一感兴趣的数据。例如,对于语言表和该语言的 cmets 表,在处理 cmets 表时,我想加入语言表的唯一原因通常是获取语言代码或限制对具有特定语言代码的人的查询。有关该语言的其他信息可能很少使用。在这种情况下,加入代码的效率可能低于加入来自IDENTITY 列的数字 id 集,将代码作为主键 - 因此作为存储在 cmets 的外键列中的内容table - 将完全消除对任何 JOIN 的需求,并获得可观的效率增益。更多时候,虽然我想从相关表中获得更多信息,但让 JOIN 更有效更重要。

【讨论】:

    【解决方案3】:

    主键:

    1. 主键只是唯一标识表中的每一行。

    2. 主键不允许重复值,NULL也不允许。

    3. 默认情况下主键是聚集索引。

    4. 一张表只能有一个主键。

    唯一密钥:

    1. 唯一键不过是唯一标识表中的每一行。

    2. 唯一键不允许重复值,但它允许(最多一个)NULL

    3. 默认情况下唯一键是非聚集索引。

    这是了解主键的水果完整链接Database Keys. 请记住,我们在一张表中只有一个聚集索引 [谈论 SQL Server 2005]。 现在,如果我们想添加另一个唯一列,那么我们将使用 Unique Key 列,因为 Unique Key 列可以添加多个。

    【讨论】:

    • “什么都不是”是什么意思?
    【解决方案4】:

    主键是任意一个候选键。原则上主键与任何其他候选键没有区别,因为在关系模型中所有键都是相等的。

    然而,SQL 有两种不同的语法来实现候选键:PRIMARY KEY 约束和 UNIQUE 约束(当然在不可为空的列上)。在实践中,它们实现了完全相同的事情,除了基本无用的限制,即每个表只能使用一次 PRIMARY KEY,而可以多次使用 UNIQUE 约束。

    因此,PRIMARY KEY 约束没有基本的“用途”。它是多余的,很容易被忽略或完全从语言中删除。然而,许多人发现在每个表中挑出一个特定的键是很方便的,因为它具有特殊的意义。有一个非常普遍的约定,即用 PRIMARY KEY 指定的键用于外键引用,尽管这完全是可选的。

    【讨论】:

      【解决方案5】:

      短版:

      • 从数据库理论的角度来看,没有。两者都只是候选键。
      • 在实践中,大多数 DMBS 都喜欢有一个“标准密钥”,可用于例如决定如何存储数据,并告诉工具和数据库客户端哪种方法是识别记录的最佳方式。

      因此将一个唯一键区分为“主键”只是一种实现方便(但很重要)。

      【讨论】:

      • 不正确,就数据库理论而言,唯一键可能具有多个空值。特别是在 SQLServer 中,这是不允许的(许多人认为这是一个缺陷),但这是 SQLServer 特定的,而不是 db-theory 的事情。因此,就 db 理论而言,唯一键不足以唯一标识一行。
      • @Jon Hanna:在数据库理论中,候选键不能包含空值。术语“唯一键”是重言式和/或用词不当。所有的键都是唯一的,而且键也是不可为空的,但是如果我们在这个意义上理解“唯一”是指 SQL 风格的 unqiue constraint,那么我们谈论的是可能包含空值的东西,因此不是根本不是“钥匙”!因此,如果“唯一密钥”被理解为“候选密钥”,那么 sleske 是正确的。我建议完全避免使用“唯一键”一词。它太容易被误解。
      • @dportas,不,因为键无法通过为空来覆盖某些行。
      • @Jon:您说的不是关系模型,而是 ER 建模概念。从上下文来看,我的假设是我们正在讨论关系模型中的键。关系模型中的键被非常精确地定义为一组属性,它们唯一地标识关系中的每个元组。如需确认,请参阅关系数据库词典、Codd 的论文或他的书,或许多其他数据库理论教科书。这是基本的,因为根据定义,每个关系都至少有一个键,而且通常不止一个。
      • 这有点跑题了,但值得一提的是,这里有一个 SQL 中 1 对 0/1 关系的示例: CREATE TABLE r (x INT NOT NULL PRIMARY KEY REFERENCES s (x), z INT NOT NULL 唯一引用 t (z));这是具有两个键的表的一个示例。可以将其中任意一个指定为“主”键。哪个键称为主键并不重要,因为所有键都有相同的用途 - 唯一标识一行。
      猜你喜欢
      • 1970-01-01
      • 2013-12-22
      • 1970-01-01
      • 1970-01-01
      • 2016-09-20
      • 2023-03-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多