主键与唯一性
理解主键、代理键与自然键、复合键,以及为何每一行都需要一个值得信赖的唯一标识符。
主键与唯一性 是 CoddyKit 上的免费 SQL Academy 课时。 这是第 2 节课,共 4 节。 你可以在下方免费阅读本课时的完整内容 — 然后在浏览器中使用内置代码编辑器和全天候 AI 导师进行实践。 这是 SQL Academy 学习路径的一部分,你的进度在网页和 CoddyKit 应用中同步。 SQL Academy 课程共包含 4 节课。
为什么每一行都需要唯一 ID
要安全地更新或删除特定行,您必须能够明确无误地定位它。
- 可以存在两个名为 "Alice Adams" 的用户
- 但不能存在两个
id = 42的用户 - 这个唯一标识符称为主键
声明主键
创建表时,您可以将某一列标记为主键:
CREATE TABLE products (
id BIGSERIAL PRIMARY KEY,
sku VARCHAR(50) NOT NULL,
name VARCHAR(200) NOT NULL,
price NUMERIC(10,2) NOT NULL
);主键 = NOT NULL + UNIQUE
PRIMARY KEY 会自动强制执行以下规则:
- NOT NULL——主键值不能缺失
- UNIQUE——不能有两行共享相同的主键值
数据库还会在主键上创建唯一索引,因此按 ID 查找的速度很快。
代理键与自然键
对于主键,您有两种选择:
- 代理键——由数据库生成的合成 ID(BIGSERIAL、UUID)。现代应用中最常见。
- 自然键——现实世界中的标识符(电子邮件、ISBN)。存在风险:人们可能会更换电子邮件地址。
最佳实践是:使用代理 ID,并在自然键上添加 UNIQUE 约束。
BIGSERIAL:自动递增整数
在 PostgreSQL 中,BIGSERIAL 会创建一个由序列支持的 64 位自动递增列。
CREATE TABLE orders (
id BIGSERIAL PRIMARY KEY,
user_id BIGINT NOT NULL,
total NUMERIC(10,2) NOT NULL
);
-- You omit id on insert and the DB fills it in:
INSERT INTO orders (user_id, total) VALUES (7, 99.50);UUID 主键
另一种选择是 128 位 UUID,适用于 ID 必须在不同系统之间保持唯一,或需要在客户端生成的情况。
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE TABLE sessions (
id UUID PRIMARY KEY DEFAULT uuid_generate_v4(),
user_id BIGINT NOT NULL,
ip INET
);复合主键
有时,自然标识符是多个列的组合:
CREATE TABLE order_items (
order_id BIGINT NOT NULL,
product_id BIGINT NOT NULL,
quantity INT NOT NULL,
PRIMARY KEY (order_id, product_id)
);
-- The pair (order_id, product_id) must be unique
-- A product can appear at most once per orderUNIQUE 约束与主键的区别
您可以将其他列声明为唯一列,而不将它们设为主键:
CREATE TABLE users (
id BIGSERIAL PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
username VARCHAR(50) UNIQUE
);
-- INSERT below fails on the second row:
INSERT INTO users (email, username) VALUES ('a@x.com', 'alice');
INSERT INTO users (email, username) VALUES ('a@x.com', 'bob'); -- ERROR插入重复项时会发生什么
如果您尝试插入重复的主键,数据库会拒绝整个语句:
ERROR: duplicate key value violates unique constraint "users_pkey" DETAIL: Key (id)=(42) already exists.
这是一件好事——它可以阻止数据在不知不觉中损坏。
按主键查找行的速度很快
主键上的唯一索引可以提供 O(log n) 的查找速度,即使数据规模达到十亿行也是如此。
-- Index Scan using users_pkey on users (cost=0.43..8.45 rows=1)
SELECT email FROM users WHERE id = 42;不要重复使用 ID
即使您删除了一行,也不要重复使用它的主键。其他表或外部系统可能仍然引用它。让序列继续递增即可——ID 的成本很低。
总结
主键为每一行提供稳定且唯一的标识。
- 优先使用代理键(BIGSERIAL 或 UUID)
- 对于不能重复的自然键,使用 UNIQUE
- 复合主键可以表示“这一对值必须唯一”
快速检查
下面哪项会由 PRIMARY KEY 隐式强制执行?
常见问题解答
「主键与唯一性」课时是免费的吗?
是的 — 「主键与唯一性」的完整文本可在网页上免费阅读。要进行交互式练习(内置代码编辑器和全天候 AI 导师)并解锁 SQL Academy 课程的其余内容,请升级到 CoddyKit PRO。 SQL Academy 课程共包含 4 节课。
「主键与唯一性」这节课中我会学到什么?
理解主键、代理键与自然键、复合键,以及为何每一行都需要一个值得信赖的唯一标识符。 你通过在浏览器中直接运行的动手代码来练习 SQL Academy,全天候 AI 导师会在你学习这节课的过程中回答你的问题。
学习 SQL Academy 需要有经验吗?
无需任何先前经验。CoddyKit 上的 SQL Academy 课程适合初学者到高级学习者,你可以从这里开始或从头开始,按照自己的节奏学习。 这是第 2 节课,共 4 节。
「主键与唯一性」课时需要多长时间?
大多数 CoddyKit 课程大约需要 5–10 分钟。每节课都很精短且互动,所以你能稳步进步,并在网页和应用中从离开的地方继续。
我能在这节 SQL Academy 课中编写并运行代码吗?
能。每节 SQL Academy 课都包含内置代码编辑器,你可以在浏览器中直接编写并运行真实代码,并获得即时 AI 反馈 — 无需本地设置。