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)

文章评论

0条评论