约束简介
在关系数据库中,我们可以在建表时指定数据类型来限制数据的合法性,但有些时候这还不够,比如限制年龄大于0或者限制折扣大于0小于1等,数据库为这些场景提供的解决方案是约束。本文将一一介绍PostgreSQL中的约束。需要注意的是关系数据库中支持列级和表级两种约束,并且一个字段上可以创建多个约束。
Check约束
1、check约束是比较常见的约束,它允许列值满足一个指定的布尔表达式。
示例如下:
CREATE TABLE products (
product_no integer,
name text,
price numeric CHECK (price > 0)
);
2、支持给约束单独命名(列或表),这样报错信息更准确,同时允许修改该约束。
示例如下:
CREATE TABLE products (
product_no integer,
name text,
price numeric CONSTRAINT positive_price CHECK (price > 0)
);
3、可以在多列上定义约束
CREATE TABLE products (
product_no integer,
name text,
price numeric CHECK (price > 0),
discounted_price numeric CHECK (discounted_price > 0),
CHECK (price > discounted_price)
);
4、需要注意的是check约束表达式为true或者null都满足约束
Not-NULL约束
1、非空约束指定字段不允许存储null值
2、非空约束通常是列级约束
3、非空约束相当于创建一个check约束,如:CHECK (column_name IS NOT NULL),但是not null方式不能给约束命名。
4、PostgreSQL也支持null约束,表示字段值可以为空。
Not null约束示例:
REATE TABLE products (
product_no integer NOT NULL,
name text NULL,
price numeric NOT NULL CHECK (price > 0)
);
唯一约束
1、唯一约束用于保证表中一列或多列数据唯一性。
2、创建唯一约束会自动创建一个唯一索引(B-tree)
3、唯一约束可以保证表中没有约束列完全相等的行,但是两个null值不相等,事实上null值与任何值都无法比较。所以即使有唯一约束,也无法避免重复值出现某个约束列是null的重复行。这与SQL标准相同。
唯一约束示例:单列约束
CREATE TABLE products (
product_no integer UNIQUE,
name text,
price numeric
);
CREATE TABLE products (
product_no integer,
name text,
price numeric,
UNIQUE (product_no)
);
CREATE TABLE products (
product_no integer,
name text,
price numeric,
CONSTRAINT must_be_different UNIQUE (product_no)
);
唯一索引示例:多列约束
CREATE TABLE example (
a integer,
b integer,
c integer,
UNIQUE (a, c)
);
主键约束
1、主键约束表示一列或几列作为一个唯一标识符,列值需要同时满足唯一和非空两个条件。
2、一张表最多只能有一个主键。
3、创建主键约束会自动在约束列上创建唯一索引,并为约束列为增加非空约束。
4、关系数据库理论要求每张表必须定义主键,PostgreSQL中并不强制,但是通常建议为每张表定义一个主键。
CREATE TABLE products (
product_no integer PRIMARY KEY,
name text,
price numeric
);
CREATE TABLE products (
product_no integer UNIQUE NOT NULL,
name text,
price numeric
);
主键约束示例:多列主键
CREATE TABLE example (
a integer,
b integer,
c integer,
PRIMARY KEY (a, c)
);
外键约束
1、外键约束指的是一张表外键约束列的值必须在另一张表中存在,用于维护两张关联表的依赖完整性。
CREATE TABLE products (
product_no integer PRIMARY KEY,
name text,
price numeric
);
CREATE TABLE orders (
order_id integer PRIMARY KEY,
product_no integer REFERENCES products (product_no),
quantity integer
);
上述实例中,orders为引用表,products为被引用表。
orders表不允许创建product_no非空且在products表中不存在的订单。
2、外键约束命名
CREATE TABLE t1 (
a integer PRIMARY KEY,
b integer,
c integer,
FOREIGN KEY (b, c) REFERENCES other_table (c1, c2)
);
3、当删除或者更新数据是,外键约束有如下策略
RESTRICT:报错,不允许删除
CASCADE:级联删除,删除被引用表数据,同时删除引用表相关记录。
SET NULL :引用字段被设置为null
SET DEFAULT:引用字段设置为默认值。
外键约束示例:
CREATE TABLE order_items (
product_no integer REFERENCES products ON DELETE RESTRICT,
order_id integer REFERENCES orders ON DELETE CASCADE,
quantity integer,
PRIMARY KEY (product_no, order_id)
);
Exclusion约束
1、排他约束用于保证某些列或者表达式上的操作符比较至少有一个返回false或者null。
2、排他约束依赖索引,可以是B-TREE或GIST类型索引。
排他约束示例:
create extension btree_gist;
create table t(
id int,
name varchar(12),
EXCLUDE USING GIST (id WITH =, name WITH =)
);
insert into t values(1,2);
insert into t values(1,2);
ERROR: conflicting key value violates exclusion constraint "t_id_name_excl"
DETAIL: Key (id, name)=(1, 2) conflicts with existing key (id, name)=(1, 2).




