在PostgreSQL建模中,主键用于保证每行记录的唯一性。除了常见的单一自增主键,联合主键(复合主键)由两张或更多字段组合而成,共同约束唯一。它并不是冷门写法,在特定的业务数据结构里往往比单字段主键更自然,也更能表达真实的实体关系。

什么是联合主键
联合主键是指在建表时通过primary key (col1, col2)的方式,把多个列定义为整体唯一标识。只要这些列的组合不重复,就可以唯一确定一行。例如下面的订单明细表:
create table order_item (
order_id bigint not null,
product_id bigint not null,
quantity int not null,
price numeric(10,2) not null,
primary key (order_id, product_id)
);
这里order_id加product_id就能唯一定位某个订单里的某个商品,不需要再建一个item_id列。
联合主键更合适的场景
1. 多对多关联表
像用户角色关系表user_role(user_id, role_id),本身只是连接两个实体的桥表,组合本身就是业务主键,用联合主键可以避免无意义的代理键。
2. 明细或子表以父标识开头
订单和订单项、账单和账单明细,子表记录总是依附父表存在。用父ID加序号或子维度做联合主键,查询时直接按父ID前缀扫描,效率较好。
3. 天然复合唯一约束的实体
例如课程选课记录(student_id, course_id),现实规则就是一个学生不能重复选同一门课,联合主键同时承担了唯一约束职责。
联合主键的注意事项
- 联合主键字段不宜过多,一般两到三个足够,否则索引体积大。
- 如果其他表要引用它做外键,对方也得存同样多的列,join书写稍繁琐。
- 高频更新的列不适合放进联合主键,因为PostgreSQL中主键变更代价较高。
简单对比
| 方式 | 适用情况 | 缺点 |
|---|---|---|
| 单一代理主键 | 无明确业务键、需要简单引用 | 可能多出无业务含义的列和索引 |
| 联合主键 | 实体由多字段自然唯一确定 | 外键引用较宽,字段更新不便 |
建模小示例
下面演示一个带外键引用的联合主键用法:
create table course (
course_id bigint primary key,
title text not null
);
create table enrollment (
student_id bigint not null,
course_id bigint not null,
enrolled_at timestamp not null,
primary key (student_id, course_id),
foreign key (course_id) references course(course_id)
);
在PostgreSQL里,当业务对象本身就用多个属性唯一表达时,联合主键往往比强行加ID更贴切。先理清实体边界与访问路径,再决定用复合键还是代理键,才能真正发挥建模的优势。
PostgreSQL联合主键复合键建模修改时间:2026-07-27 01:45:19