pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。
本文由 Herouth Maoz 撰写
本文最初发表在邮件列表上, 是对下面这个问题的回答: "PRIMARY KEY 和 UNIQUE 约束有什么区别?"。
Subject: Re: [QUESTIONS] PRIMARY KEY | UNIQUE
下面两者有什么区别:
PRIMARY KEY(fields,...) 和
UNIQUE (fields,...)
- 这是一个别名吗?
- 如果 PRIMARY KEY 已经是唯一的,那为什么
还会有另一种名为 UNIQUE 的键?
主键是用于标识特定行的字段(或字段组合)。例如, 标识一个人的社会保障号码。
单纯的 UNIQUE 字段组合与行的标识无关, 它只是一个完整性约束。举个例子:我有一些链接集合。每个集合 由一个唯一的编号标识,这个编号就是主键。这个键在关系中使用。
不过,我的应用还要求每个集合有一个唯一的名称。 为什么?这样想要修改集合的人才能识别它。如果你有两个名为 "Life Science"的集合,就很难知道标记为 24433 的那个才是 你需要的,而标记为 29882 的那个不是。
因此,用户通过名称来选择集合。为此我们在数据库中 确保名称是唯一的。但是,数据库中没有其他表通过集合名称与 collections 表关联——那样做会非常低效。
此外,尽管是唯一的,集合名称实际上并不定义集合! 例如,如果有人决定把集合的名称从"Life Science"改为"Biology", 它仍然是同一个集合,只是名称不同而已。只要名称保持唯一, 这就没问题。
因此:
主键:
用于标识行并建立到它的关联。
不可能(或很难)更新。
不应允许 NULL。
唯一字段(组合):
用作访问行的另一种途径。
只要保持唯一就可以更新。
可以接受 NULL。
那么,为什么标准 SQL 语法中没有显式定义 非唯一键?你必须理解,索引是与实现相关的。SQL 不定义实现,只定义数据库中数据之间的关系。Postgres 确实允许非唯一索引,但用于实施 SQL 键的索引总是唯一的。
因此,你可以按表中列的任意组合查询一个表,即使你 在这些列上并没有索引。索引只是每种 RDBMS 向你提供的 一种实现上的辅助手段,目的是让常用的查询执行得更加高效。 有些 RDBMS 可能会提供额外的措施,例如把键保存在 主存中。它们会有一条特殊的命令,例如
CREATE MEMSTORE ON <table> COLUMNS <cols>
(这不是一条实际存在的命令,只是一个例子)。
事实上,当你创建主键或唯一的字段组合时,SQL 规范中没有任何地方说会创建索引,也没有说通过键检索数据 会比顺序扫描更高效!
所以,如果你想用一个非唯一的字段组合作为辅助键, 你其实根本不必指定任何东西——直接按那个组合开始检索就行了! 但如果你想让检索更加高效,就得求助于你的 RDBMS 供应商提供的手段——无论是索引、我虚构的 MEMSTORE 命令,还是一个 聪明的 RDBMS,它会根据你基于特定键组合发送的大量查询, 在你不知情的情况下创建索引……(它从经验中学习)。
译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。