PostgreSQL 创建外键约束
外键又称为外键约束,英文 foreign key constraint,外键是一个表中用于标识另一张表中的一个字段或多个字段。包含外键的表称为引用表,外键引用表称为被引用表。外键约束是指引用字段必须在被引用字段中出现,被引用字段需要是唯一约束或主键。
1. 创建外键约束
通常在创建表的时候就会为其指定外键约束,下面通过一个例子,展示如何创建外键约束。
(1)创建父表 parent,该表作为被引用表。
create table parent(id int, name text, age int, primary key(id));
(2)创建子表 child,该表作为引用表。
create table child(id int, name text, parent_id int references parent(id), primary key(id));
以上子表 child 的 parent_id 字段上创建了外键约束,在 psql 中执行 \d+ 查看表结构可以看到外键信息,如下:
postgres=# \d+ child Table "public.child" Column | Type | Collation | Nullable | Default | Storage | Stats target | Description -----------+---------+-----------+----------+---------+----------+--------------+------------- id | integer | | not null | | plain | | name | text | | | | extended | | parent_id | integer | | | | plain | | Indexes: "child_pkey" PRIMARY KEY, btree (id) Foreign-key constraints: "child_parent_id_fkey" FOREIGN KEY (parent_id) REFERENCES parent(id) Access method: heap
有了外键约束,子表 child 的字段 parent_id 必须是 parent 表 id 字段包含的值,如果没有对应的值,则会报错,如下:
postgres=# insert into parent values(1,'he',40); INSERT 0 1 postgres=# insert into child values(1,'his child',2); ERROR: insert or update on table "child" violates foreign key constraint "child_parent_id_fkey" DETAIL: Key (parent_id)=(2) is not present in table "parent".
2. alter table add constraint 动态添加外键约束
除了在创建表时指定外键,也可以在创建表之后通过 alter table add constraint 语句动态地为表添加外键约束,如下:
create table child2 (like child including all); alter table child2 add constraint fk_parent_id foreign key (parent_id) references parent(id);
查询表 child2 表结构,如下:
postgres=# \d+ child2 Table "public.child2" Column | Type | Collation | Nullable | Default | Storage | Stats target | Description -----------+---------+-----------+----------+---------+----------+--------------+------------- id | integer | | not null | | plain | | name | text | | | | extended | | parent_id | integer | | | | plain | | Indexes: "child2_pkey" PRIMARY KEY, btree (id) Foreign-key constraints: "fk_parent_id" FOREIGN KEY (parent_id) REFERENCES parent(id) Access method: heap
3. 启用或禁用外键约束
可以在不删除外键约束的情况下禁用或者重新启用外键约束,禁用外键约束后插入一条不满足外键约束的记录则不再会报错,如下:
postgres=# alter table child disable trigger all; ALTER TABLE postgres=# insert into child values(2,'his child',3); INSERT 0 1
启用外键约束:
postgres=# alter table child enable trigger all; ALTER TABLE postgres=# insert into child values(3,'his child',3); ERROR: insert or update on table "child" violates foreign key constraint "child_parent_id_fkey" DETAIL: Key (parent_id)=(3) is not present in table "parent".
由以上语法可以猜测 PostgreSQL 的外键约束是通过触发器机制实现的,禁用了触发器,则外键约束也被禁用。
4. 删除外键约束
通过 alter table drop constraint 语法删除外键约束。
alter table child drop constraint child_parent_id_fkey;
5. 获取外键约束的定义
PostgreSQL 提供了系统函数 pg_get_constraintdef() 来获取外键的定义信息,其参数为外键的 oid,可从元数据表 pg_constraint 中获取,示例如下:
postgres=# select pg_get_constraintdef(41128); pg_get_constraintdef ----------------------------------------------- FOREIGN KEY (parent_id) REFERENCES parent(id) (1 row)