六、FOREIGN KEY ---- 外键约束

外键可以是单个字段,也可以是多个字段。所谓的外键约束就是引用字段必须在被引用字段中存在,除非引用字段部分为NULL或全部为NULL(由MATCH TYPE决定),否则INSERT或UPDATE时将返回失败,且被引用字段必须有唯一约束或是主键。

外键约束语法相对较复杂一点,创建外键的语法如下:

ALTER TABLE tbl_foreign CONSTRAINT fk_constraint FOREIGN KEY(col1,col2) REFERENCES tbl_foreign_refd(refd_col1,refd_col2) MATCH [SIMPLE|FULL] ON DELETE [CASCADE|NO ACTION] ON UPDATE [CASCADE|NO ACTION];

其中:

tbl_foreign             : 引用表

fk_constraint           : 外键约束名称

(col1,col2)             : 引用表中引用字段

tbl_foreign_refd        : 被引用表

(refd_col1,refd_col2)   : 被引用表中被引用字段,和(col1,col2)对应

MATCH [SIMPLE|FULL]     : 外键匹配模式,如果引用字段全部不是NULL,则强匹配,否则根据匹配模式进行弱匹配。

--SIMPLE,默认值,只要引用字段中任一字段为NULL,则不要求与被引用字段强匹配;

--FULL,只有引用字段全部为NULL,才不要求与被引用字段强匹配。

ON DELETE [CASCADE | NO ACTION] : 默认NO ACTION

--CASCADE,删除被引用表数据级联删除引用表数据

--NO ACTION,删除被引用表数据必须先删除引用表数据,否则,如果引用表如果存在数据,直接删除被引用表数据返回失败。

ON UPDATE [CASCADE | NO ACTION] : 默认NO ACTION

--CASCADE,更新被引用表时级联更新引用表数据

--NO ACTION,更新被引用表时必须先删除引用表数据,否则,如果引用表存在数据,直接更新被引用表数据返回失败。

1.创建测试表(引用表tbl_foreign和被引用表tbl_foreign_refd)

create table tbl_foreign_refd(
a int not null,
b int not null,
c varchar
);
alter table tbl_foreign_refd add constraint pk_tbl_foreign_refd_a_b primary key(a,b); create table tbl_foreign(
a int,
b int,
c varchar
);
alter table tbl_foreign add constraint fk_tbl_foreign_a_b foreign key(a,b) references tbl_foreign_refd(a,b);

上表中完整外键其实如下,因为match,on delete,on update会自动使用默认值。

test=# alter table tbl_foreign add constraint fk_tbl_foreign_a_b foreign key(a,b) references tbl_foreign_refd(a,b) match simple on delete no action on update no action;

测试例1.match simple on delete no action on update no action

test=# insert into tbl_foreign_refd (a,b) values (1,1),(1,2),(1,3);
INSERT 0 3
test=# insert into tbl_foreign(a,b) values (1,1),(1,2);
INSERT 0 2 test=# insert into tbl_foreign(a,b) values (2,1);
ERROR: insert or update on table "tbl_foreign" violates foreign key constraint "fk_tbl_foreign_a_b"
DETAIL: Key (a, b)=(2, 1) is not present in table "tbl_foreign_refd". test=# insert into tbl_foreign(a) values (2);
INSERT 0 1
test=# insert into tbl_foreign(a) values (1);
INSERT 0 1
test=# select * from tbl_foreign;
a | b | c
---+------+------
1 | 1 | NULL
1 | 2 | NULL
2 | NULL | NULL
1 | NULL | NULL
(4 rows)
test=# delete from tbl_foreign_refd where a=1 and b=1;
ERROR: update or delete on table "tbl_foreign_refd" violates foreign key constraint "fk_tbl_foreign_a_b" on table "tbl_foreign"
DETAIL: Key (a, b)=(1, 1) is still referenced from table "tbl_foreign". test=# update tbl_foreign_refd set a=3 where a=1 and b=1;
ERROR: update or delete on table "tbl_foreign_refd" violates foreign key constraint "fk_tbl_foreign_a_b" on table "tbl_foreign"
DETAIL: Key (a, b)=(1, 1) is still referenced from table "tbl_foreign".

测试例2.match full on delete cascade on update cascade

删除外键约束,清空数据,重新增加外键

test=# alter table tbl_foreign drop constraint fk_tbl_foreign_a_b ;
ALTER TABLE
test=# delete from tbl_foreign;
DELETE 4
test=# alter table tbl_foreign add constraint fk_tbl_foreign_a_b foreign key(a,b) references tbl_foreign_refd(a,b) match full on delete cascade on update cascade;
ALTER TABLE
test=# insert into tbl_foreign(a,b) values (1,1),(1,2);
INSERT 0 2 test=# insert into tbl_foreign(a) values (2);
ERROR: insert or update on table "tbl_foreign" violates foreign key constraint "fk_tbl_foreign_a_b"
DETAIL: MATCH FULL does not allow mixing of null and nonnull key values. test=# insert into tbl_foreign(c) values (2);
INSERT 0 1
test=# select * from tbl_foreign;
a | b | c
------+------+------
1 | 1 | NULL
1 | 2 | NULL
NULL | NULL | 2
(3 rows) test=# delete from tbl_foreign_refd where a=1 and b=1;
DELETE 1
test=# update tbl_foreign_refd set a=2 where a=1 and b=2;
UPDATE 1
test=# select * from tbl_foreign;
a | b | c
------+------+------
NULL | NULL | 2
2 | 2 | NULL
(2 rows) test=# update tbl_foreign set a=3 where a=2;
ERROR: insert or update on table "tbl_foreign" violates foreign key constraint "fk_tbl_foreign_a_b"
DETAIL: Key (a, b)=(3, 2) is not present in table "tbl_foreign_refd".

2.删除外键约束

alter table tbl_foreign drop constraint fk_tbl_foreign_a_b ;

3.增加外键约束

和唯一键,主键一样,增加外键约束前首先要删除脏数据,对外键来说脏数据针对不同的match type来说是不一样的。

match simple : 引用字段全部是NOT NULL,且在被引用表中不存在的。

match full   : 引用字段部分是NULL和全部是NOT NULL且在被引用表中不存在的。

情况一:增加match simple类型外键

第一步:删除外键,清空表,写入测试数据

test=# alter table tbl_foreign drop constraint fk_tbl_foreign_a_b ;
ALTER TABLE
test=# delete from tbl_foreign;
DELETE 2
test=# insert into tbl_foreign(a,b) values (1,2),(2,2),(1,1);
INSERT 0 3
test=# insert into tbl_foreign(a) values (3),(4);
INSERT 0 2
test=# insert into tbl_foreign(c) values (5);
INSERT 0 1
test=# select * from tbl_foreign;
a | b | c
------+------+------
1 | 2 | NULL
2 | 2 | NULL
1 | 1 | NULL
3 | NULL | NULL
4 | NULL | NULL
NULL | NULL | 5
(6 rows) test=# select * from tbl_foreign_refd ;
a | b | c
---+---+------
1 | 3 | NULL
2 | 2 | NULL
(2 rows)

对于要增加的外键来说,(1,1,NULL),(1,2,NULL)是脏数据。

第二步:查询脏数据

test=# select * from tbl_foreign where not exists (select null from tbl_foreign_refd where tbl_foreign_refd.a=tbl_foreign.a and tbl_foreign_refd.b=tbl_foreign.b) and a is not null and b is not null;
a | b | c
---+---+------
1 | 1 | NULL
1 | 2 | NULL
(2 rows)

第三步:删除脏数据

将上面SQL语句中的select替换成delete即可。

test=# delete from tbl_foreign where not exists (select null from tbl_foreign_refd where tbl_foreign_refd.a=tbl_foreign.a and tbl_foreign_refd.b=tbl_foreign.b) and a is not null and b is not null;
DELETE 2

第四步:增加外键

test=# alter table tbl_foreign add constraint fk_tbl_foreign_a_b foreign key(a,b) references tbl_foreign_refd(a,b) match simple;
ALTER TABLE

情况二:增加match full类型外键

第一步:删除外键,清空表,写入测试数据

test=# alter table tbl_foreign drop constraint fk_tbl_foreign_a_b ;
ALTER TABLE
test=# delete from tbl_foreign;
DELETE 4
test=# insert into tbl_foreign(a,b) values (1,2),(2,2),(1,1);
INSERT 0 3
test=# insert into tbl_foreign(a) values (3),(4);
INSERT 0 2
test=# insert into tbl_foreign(c) values (5);
INSERT 0 1
test=# select * from tbl_foreign;
a | b | c
------+------+------
1 | 2 | NULL
2 | 2 | NULL
1 | 1 | NULL
3 | NULL | NULL
4 | NULL | NULL
NULL | NULL | 5
(6 rows) test=# select * from tbl_foreign_refd ;
a | b | c
---+---+------
1 | 3 | NULL
2 | 2 | NULL
(2 rows)

对于要增加的外键来说,(1,1,NULL),(1,2,NULL),(3,NULL,NULL),(4,NULL,NULL)是脏数据。

第二步:查询脏数据

test=# select * from tbl_foreign where not exists (select null from tbl_foreign_refd where tbl_foreign_refd.a=tbl_foreign.a and tbl_foreign_refd.b=tbl_foreign.b) and ((a is not null and b is not null) or (a is not null and b is null) or(a is null and b is not null));
a | b | c
---+------+------
1 | 1 | NULL
1 | 2 | NULL
3 | NULL | NULL
4 | NULL | NULL
(4 rows)

第三步:删除脏数据

将上面SQL语句的SELECT替换成DELETE即可。

test=# delete from tbl_foreign where not exists (select null from tbl_foreign_refd where tbl_foreign_refd.a=tbl_foreign.a and tbl_foreign_refd.b=tbl_foreign.b) and ((a is not null and b is not null) or (a is not null and b is null) or(a is null and b is not null));
DELETE 4

第四步:增加外键约束

test=# alter table tbl_foreign add constraint fk_tbl_foreign_a_b foreign key(a,b) references tbl_foreign_refd(a,b) match full;
ALTER TABLE

postgresql----数据库表约束----FOREIGN KEY的更多相关文章

  1. MySQL数据库之-foreign key 外键(一对多、多对多、一对一)、修改表、复制表

    摘要: 外键 一对多 外键 多对多 外键 一对一 --------------------------------------------------------------------------- ...

  2. 数据库六大约束用法:主键(primary key)、外键(foreign key)、非空(not null)、默认(default)、检查(check)、唯一(unique)

    1. 数据库有六大约束 主键(primary key) 外键(foreign key):被参照的键必须有唯一约束或是主键 非空(not null) 默认(default) 检查(check):orac ...

  3. 关于数据库主从表、主键PRIMARY KEY 外键约束 FOREIGN KEY 约束----NOT NULL,DEFAULT,CHECK

    如果由两个列共同组成主键,而且一个子表将主键作为可为空值的外键来继承,就可能得到错误的数据.可在一个外键列中插入有效的值,但在另一个外键列中插入空值.然后,可添加一个数据表检查约束,在可为空的外键中检 ...

  4. postgresql数据库primary key约束/not null约束/unique约束及default值的添加与删除、列的新增/删除/重命名/数据类型的更改

    如果在建表时没有加primary key约束.not null约束.unique约束.default值,而是创建完表之后在某个字段添加的话 1.primary key约束的添加与删除 给red_pac ...

  5. MySql数据库插入或更新报错:Cannot add or update a child row: a foreign key constraint fails

    具体报错信息: Cannot add or update a child row: a foreign key constraint fails (`xxx`.`AAA`, CONSTRAINT `t ...

  6. 数据库基本表创建 完整性约束 foreign Key

    理解以下几张表的内容,根据实际情况设计属性名.数据类型.及各种完整性约束(primary key.foreign key.not null.unique.check),用数据定义语言实现,然后设计实验 ...

  7. [MySQL数据库之表的约束条件:primary key、auto_increment、not null与default、unique、foreign key:表与表之间建立关联]

    [MySQL数据库之表的约束条件:primary key.auto_increment.not null与default.unique.foreign key:表与表之间建立关联] 表的约束条件 约束 ...

  8. 数据库中的參照完整性(Foreign Key)

    之前在项目中遇到了这样一个问题,我举得简单的样例来说明. 比方我们有两个表,一个表(department)存放的是部门的信息,比如部门id,部门名称等:还有一个表是员工表(staff),员工表里面肯定 ...

  9. Oracle数据库-primary key/foreign key和references关系

    主要介绍一下个人对主键(primary key).外键(foreign key).候选键(Candidate key).超键(super key).references的总结 概念: 主键:用户选择元 ...

随机推荐

  1. Qt::WA_DeleteOnClose 造成的野指针问题

    今天遇到了一个由Qt::WA_DeleteOnClose造成的野指针问题,在网上搜到的一个求助贴如下(http://bbs.csdn.net/topics/380182058): 主窗口类QMainW ...

  2. 关于Cocos2d-x物理引擎用到的类和使用

    其实就是这三类PhysicsWorld类,PhysicsBody类,PhysicsShape类. 1.PhysicsWorld类 PhysicsWorld对象代表Cocos2d-x中的物理世界,这个世 ...

  3. 【转】C# 调用WebService的方法

    很少用C#动态的去调用Web Service,一般都是通过添加引用的方式,这样的话是自动成了代理,那么动态代理调用就是我们通过代码去调用这个WSDL,然后自己去生成客户端代理.更多的内容可以看下面的两 ...

  4. PHP wamp server问题

    只能说各种不顺,天热人烦! 问题一.wampapache服务不能启动之VCRUNTIME140.DLL文件丢失. 这个是缺少VC运行库,查找并安装相应的文件即可. 问题二.wampapche服务不能启 ...

  5. matplotlib中的legend()——用于显示图例

    legend()的一个用法: 当我们有多个 axes时,我们如何把它们的图例放在一起呢?? 我们可以这么做: import matplotlib.pyplot as plt import numpy ...

  6. Oracle 12c安装详细步骤,带截图

    1,在官网上下载oracle的压缩文件,两个都要下载. 并两个同时选中解压在一个文件夹里面. 2,解压之后,如下图,点击setup.exe稍等一会儿 ,3,开始安装: 不选点击下一步,或者直接点击下一 ...

  7. 【Java面试题】10 abstract的method是否可同时是static,是否可同时是native,是否可同时是synchronized?

    1.abstract是抽象的,指的是方法只有声明而没有实现,他的实现要放入声明该类的子类中实现. 2.static是静态的,是一种属于类而不属于对象的方法或者属性 3.synchronized 是同步 ...

  8. java web - 为什么要使用spring struts

    1.软件里有很多优秀的框架,有一种类型的框架,它的特点是建立在一个现有技术的基础上,提供和现有技术一样业务功能的技术框架,这个新的技术框架比原技术更加易用,更加健壮同时功能更加强大,例如:jQuery ...

  9. jQuery实现HTML表格单元格的合并功能

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  10. ReSharper插件功能介绍

    ReSharper是一款功能非常强悍的Visual Studio的辅助插件,这款插件可用于C#,VB.net,XML,Asp.net,XAML,和构建脚本.ReSharper 9.1版本大改进对 Ja ...