PostgreSQL 支持哪些约束类型?
PostgreSQL 提供了多种约束(Constraints)来保证数据库中数据的准确性和可靠性(即数据完整性)。
PostgreSQL 支持的约束类型主要有以下 6 种,外加 1 种常被一同提及的属性:
1. 检查约束 (CHECK)
作用:确保列中的值满足指定的布尔表达式(必须为真)。
应用场景:限制年龄必须大于 0,商品价格不能为负数等。
示例:
CREATE TABLE products (
product_no integer,
name text,
price numeric CHECK (price > 0), -- 列级约束
discounted_price numeric,
CHECK (discounted_price > 0 AND discounted_price < price) -- 表级约束
);
2. 非空约束 (NOT NULL)
作用:确保某列的数据不能包含 NULL 值。
应用场景:用户名、密码等必须填写的字段。
示例:
CREATE TABLE users (
id serial PRIMARY KEY,
username varchar(50) NOT NULL
);
3. 唯一约束 (UNIQUE)
作用:确保一列或多列组合中的所有数据都是互不相同的(唯一的)。
注意:在 PostgreSQL 中,默认情况下 NULL 值被认为是互不相同的,因此带有 UNIQUE 约束的列可以插入多个 NULL 值(PostgreSQL 15 引入了 UNIQUE NULLS NOT DISTINCT 可以改变此行为)。
示例:
CREATE TABLE users (
id serial PRIMARY KEY,
email text UNIQUE -- 所有的 email 必须不同
);
4. 主键约束 (PRIMARY KEY)
作用:唯一地标识表中的每一行。它实际上是 UNIQUE 和 NOT NULL 的结合体。一张表只能有一个主键(可以由多列组成,即复合主键)。
应用场景:用户 ID、订单号等。
示例:
CREATE TABLE orders (
order_id serial PRIMARY KEY, -- 单列主键
product_id integer
);
-- 复合主键示例
CREATE TABLE order_items (
order_id integer,
product_id integer,
PRIMARY KEY (order_id, product_id)
);
5. 外键约束 (FOREIGN KEY)
作用:保证一个表中的数据匹配另一个表中的数据(通常是另一个表的主键或唯一键)。用于维护表与表之间的引用完整性。
行为控制:可以设置 ON DELETE 和 ON UPDATE 的级联操作(如 CASCADE, RESTRICT, SET NULL, SET DEFAULT)。
示例:
CREATE TABLE orders (
order_id serial PRIMARY KEY,
user_id integer REFERENCES users(id) ON DELETE CASCADE
-- 当 users 表中对应记录被删除时,级联删除对应的订单记录
);
6. 排他约束 (EXCLUDE) —— PostgreSQL 特有/高级特性
作用:排他约束是 UNIQUE 约束的泛化版本。它保证如果将任意两行在指定的列或表达式上使用指定的操作符进行比较,不仅所有的比较都返回真。
应用场景:最经典的场景是防止时间段重叠(例如:同一个会议室在同一时间内不能被预订两次)、地理空间不重叠等。
示例(防止会议室预订时间重叠,通常需要安装 btree_gist 扩展):
CREATE EXTENSION btree_gist;
CREATE TABLE room_reservations (
room_id text,
reservation_period daterange,
EXCLUDE USING gist (
room_id WITH =,
reservation_period WITH && -- '&&' 是范围重叠操作符
)
);
补充:默认值 (DEFAULT)
虽然 DEFAULT 在底层系统中严格来说不被视为“约束”(Constraint),而在日常数据库设计中,它经常与约束放在一起讨论。
作用:如果在插入数据时没有为该列提供值,系统会自动填入默认值。
示例:
CREATE TABLE posts (
id serial PRIMARY KEY,
title text NOT NULL,
created_at timestamp DEFAULT CURRENT_TIMESTAMP -- 默认使用当前时间
);
总结
- 最常用:
NOT NULL,PRIMARY KEY,FOREIGN KEY - 业务逻辑控制:
UNIQUE,CHECK - 高级/复杂场景(如时间段/空间排他):
EXCLUDE(这是 PostgreSQL 极其强大的一个差异化特性)