主键与外键的关系、级联保存、更新、删除

主键与外键的关系、级联保存、更新、删除

http://www.alixixi.com/ePrint.asp?from=dev&id=34852

 

正文:
--建立数据库
create database test;
go

--建立表customers
create table customers(
id int identity(1,1) not null,
name varchar(15),
age int,
primary key(id)
);
go

--建立表orders
create table orders(
id int identity(1,1) not null,
order_number varchar(15),
price money,
customer_id int,
primary key(id)
);
go

--对表orders插入数据,以检测money数据类型,结果为:69.0000
insert into orders(price) values(69);
select * from orders;

--增加外键与关系约束
alter table orders add constraint FK_CUSTOMER foreign key (customer_id) references customers(id);
go

--级联删除、更新
alter table orders add constraint FK_CUSTOMER foreign key (customer_id) references customers(id)
on delete cascade on update cascade;
go

--级联删除
alter table orders add constraint FK_CUSTOMER foreign key (customer_id) references customers(id)
on delete cascade;
go
=====================================================================================================
--
insert into customers values('张三',25);
insert into customers values('李四',25);

--如果设置了级联插入,那么在向子表orders插入的customer_id(外键)
--必须在父表customers中存在此id(主键)
insert into orders values(1,50,5);

--如果设置了级联删除,删除父表customers中id=5的记录,
--也会删除子表orders中customer_id=5的记录,
delete from customers where id=5


--查询
select * from customers;
select * from orders

 

 

 

SQL主键和外键的删除规则说明

http://www.hake.cc/a/shujuku/mssql/2011/0918/21683.html

 

 

SQL表中经常包含外键关系,删除一个表的数据就会影响其他的表,下面将为您介绍SQL主键和外键的删除规则说明,供您参考,希望对您有所帮助。

删除规则和更新规则:
指定当数据库的最终用户尝试删除或更新某一行,而该行包含外键关系所涉及的数据时所发生的情况。

如果设置为:

 

无操作:当在删除或更新主键表的数据时,将显示一条错误信息,告知用户不允许执行该删除或更新操作,删除或更新操作将会被回滚。

 

层叠:删除或更新包含外键关系中所涉及的数据的所有行。
说明:“层叠”在SQL server 2000中又叫“级联”。

 

设置空:这是SQL server 2005新增的功能。如果表的所有外键列都可以接受空值,则将该值设置为空。
说明:要将外键的删除规则和更新规则设为“设置空”,则该外键必须是可以为空的字段。

 

设置默认值:这是SQL server 2005新增的功能。如果表的所有外键列都已定义了默认值,则将该值设置为该列定义的默认值。
说明:要将外键的删除规则和更新规则设置为“设置默认值”,该外键必须是有默认值的字段。

附加:

 

SQLServer2005

http://blog.sina.com.cn/s/blog_707a4cbf0100qz6c.html

表T_Device:

DeviceID(主键)

TypeID(外键,引用到T_Type表的TypeID字段)

表T_Type:

TypeID(主键)

如图:

在表设计器里面T_Device表的TypeID字段右键单击,弹出菜单上选择关系,如图:

在弹出的外键关系对话框中的INSERT和UPDATE规范中

更新规则:层叠(默认为无操作)

删除规则:层叠(默认为无操作)

可以实现级联操作

如图:

 

这时删除表T_Type表中的一条记录,会自动删除T_Device表中对应的记录集,例如如下关系:

T_Device:

DeviceID        TypeID

1                      3

2                      1

3                      1

4                      2

5                      1

T_Type:

TypeID

1

2

3

删除T_Type表中TypeID为1的记录的时候,T_Device表中的对应的TypeID为1的记录集都会被删除。

 

下面的理解是错误的:

删除T_Device表中的一条记录会对应删除T_Type表中对应的记录,例如,删除T_Device表中TypeID为3的那条记录,会级联删除T_Type表中的TypeID为3的记录。

这种理解的错误在于,如果删除T_Device表中TypeID为1的一条记录(如语句delete from table T_Device where DeviceID = 2),那么如果对应的T_Type表中的TypeID为1的记录被删除了,则T_Device表中DeviceID为3和5的记录对应的TypeID就失效了,这样破坏了外键关联的正确性。

这种理解错误的根源在于没有搞清楚外键两边谁是引用,谁是实体,也没有搞清楚级联删除的意义在于除实体的时候级联的删除其所有引用的问题。

在上述例子中对于T_Device表来讲,T_Type表中的记录为实体,T_Device表中的TypeID字段为引用

 

另外,外键约束保证了数据的逻辑完整性,级联操作只适用于主表(或被引用表)的删除(delete)和更新(Update)操作,

不适用于从表(或引用表)的插入(Insert)操作,因此不要想象如下代码可以被执行:

insert into T_Device values(1,3); 错错错,这个是可以执行的,实例验证

T_Type表里面只要有相应的数据就可以执行

如果认为在T_Device表中插入一条记录的同时,在T_Type表中会插入相应的被关联到T_Device表的记录是不对的,因为如果再执行insert into dev values(2,3);会如何呢?T_Type表中难道会存在两条TypeID为3的记录吗,这样违背了主键唯一性,因此做插入操作只能是先插入主表(或被引用表),然后插入从表(引用表)。

保存的时候先保存T_Type表,记得一定要保存表,否则主键个外键关系实际是没有创建的


MySQL中利用外键实现级联删除、更新

http://linghongli.iteye.com/blog/649796
MySQL支持外键的存储引擎只有InnoDB,在创建外键的时候,要求父表必须有对应的索引,子表在创建外键的时候也会自动创建对应的索引。在创建索引的时候,可以指定在删除、更新父表时,对子表进行的相应操作,包括RESTRICT、NO ACTION、SET NULL和CASCADE。其中RESTRICT和NO ACTION相同,是指在子表有关联记录的情况下父表不能更新CASCADE表示父表在更新或者删除时,更新或者删除子表对应记录;SET NULL则是表示父表在更新或者删除的时候,子表的对应字段被SET NULL。
因为只有InnoDB引擎才允许使用外键,所以,我们的数据表必须使用InnoDB引擎。我所使用的版本是Mysql5.1版本的,过程如下:
创建数据库:
Create database test;
创建两个表,其中第一个表的”id”是第二个表(userinfo)的外键:
CREATE TABLE `user` (
`id` int(4) NOT NULL,
`sex` enum('f','m') DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
CREATE TABLE `userinfo` (
`sn` int(4) NOT NULL AUTO_INCREMENT,
`userid` int(4) NOT NULL,
`info` varchar(20) DEFAULT NULL,
PRIMARY KEY (`sn`),
KEY `userid` (`userid`),
CONSTRAINT `userinfo_ibfk_1` FOREIGN KEY (`userid`) REFERENCES `user` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
注意:
1、存储引擎必须使用InnoDB引擎;
2、外键必须建立索引;
3、外键绑定关系这里使用了“ ON DELETE CASCADE ” “ON UPDATE CASCADE”,意思是如果外键对应数据被删除或者更新时,将关联数据完全删除或者相应地更新。更多信息请参考MySQL手册中关于InnoDB的文档;
好,接着我们再来插入数据测试:
INSERT INTO `user` (`id`,`sex`)
VALUES ('1', 'f'), ('2', 'm'), ('3', 'f');
INSERT INTO `userinfo` (`sn`,`userid`,`info`)
VALUES ('1', '1', '2005054dsf'),
('2', '1', 'fdsfewfdsfds'),
('3', '1', 'gdsgergergrtre'),
('4', '2', 'et34t5435435werwe'),
('5', '2', '435rtgtrhfghfg'),
('6', '2', 'ret345tr4345'),
('7', '3', 'fgbdfvbcbfdgr'),
('8', '3', '45r2343234were'),
('9', '3', 'wfyhtyjtyjyjy');
我们先看一下当前数据表的状态:
mysql> show tables;
+----------------+
| Tables_in_test |
+----------------+
| user |
| userinfo |
+----------------+
2 rows in set (0.00 sec)
User表中的数据:
mysql> select * from user;
+----+------+
| id | sex |
+----+------+
| 1 | f |
| 2 | m |
| 3 | f |
+----+------+
3 rows in set (0.00 sec)
Userinfo表中的数据:
mysql> select * from userinfo;
+----+--------+-------------------+
| sn | userid | info |
+----+--------+-------------------+
| 1 | 1 | 2005054dsf |
| 2 | 1 | fdsfewfdsfds |
| 3 | 1 | gdsgergergrtre |
| 4 | 2 | et34t5435435werwe |
| 5 | 2 | 435rtgtrhfghfg |
| 6 | 2 | ret345tr4345 |
| 7 | 3 | fgbdfvbcbfdgr |
| 8 | 3 | 45r2343234were |
| 9 | 3 | wfyhtyjtyjyjy |
+----+--------+-------------------+
9 rows in set (0.00 sec)
对于建立以上不表,相信对大家也没什么难度了。好的,下面我们就要试验我们的级联删除功能了。
我们将删除user表中id为2的数据记录,看看userinf表中userid为2的相关子纪录是否会自动删除:
执行删除操作成功!
mysql> delete from `user` where `id`='2';
Query OK, 1 row affected (0.03 sec)
看看user表中已经没有id为2的数据记录了!
mysql> select * from user;
+----+------+
| id | sex |
+----+------+
| 1 | f |
| 3 | f |
+----+------+
2 rows in set (0.00 sec)
再看看userinfo表中已经没有userid为2的3条数据记录了,对应数据确实自动删除了!
mysql> select * from userinfo;
+----+--------+----------------+
| sn | userid | info |
+----+--------+----------------+
| 1 | 1 | 2005054dsf |
| 2 | 1 | fdsfewfdsfds |
| 3 | 1 | gdsgergergrtre |
| 7 | 3 | fgbdfvbcbfdgr |
| 8 | 3 | 45r2343234were |
| 9 | 3 | wfyhtyjtyjyjy |
+----+--------+----------------+
6 rows in set (0.00 sec)
更新的操作也类似,因为我们在前面建表的时候已经定义外键删除、更新操作都是CASCADE,所以在这里可以直接测试数据。
将user表中原来id为1的数据记录更改为id为4,执行如下:
mysql> update user set id=4 where id='1';
Query OK, 1 row affected (0.03 sec)
Rows matched: 1 Changed: 1 Warnings: 0
现在去看看两个表中是数据是否发生了变化:
mysql> select * from user;
+----+------+
| id | sex |
+----+------+
| 3 | f |
| 4 | f |
+----+------+
2 rows in set (0.00 sec)
mysql> select * from userinfo;
+----+--------+----------------+
| sn | userid | info |
+----+--------+----------------+
| 1 | 4 | 2005054dsf |
| 2 | 4 | fdsfewfdsfds |
| 3 | 4 | gdsgergergrtre |
| 7 | 3 | fgbdfvbcbfdgr |
| 8 | 3 | 45r2343234were |
| 9 | 3 | wfyhtyjtyjyjy |
+----+--------+----------------+
6 rows in set (0.00 sec)
比较原来的表可以发现它们的确已经更新成功了,测试完成!!!这也就实现了用外键对多个相关联的表做同时删除、更新的操作,从而保证了数据的一致性。 
 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值