外键的作用,主要有两个:
一个是让数据库自己通过外键来保证数据的完整性和一致性
一个就是能够增加ER图的可读性
有些人认为外键的建立会给开发时操作数据库带来很大的麻烦.因为数据库有时候会由于没有通过外键的检测而使得开发人员删除,插入操作失败.他们觉得这样很麻烦
其实这正式外键在强制你保证数据的完整性和一致性.这是好事儿.
外键是数据库一级的一个完整性约束,就是数据库基础理论书中所说的“参照完整性”的数据库实现方式。
外键属性当然是可以去掉的,如果你不想再用这种约束,对编程当然不会有什么影响,但相应的录入数据的时候就不对录入的数据进行“参照完整性”检查了。
例如有两个表
A(a,b) :a为主键,b为外键(来自于B.b)
B(b,c,d) :b为主键
如果我把字段b的外键属性去掉,对编程没什么影响。
如上面,A中的b要么为空,要么是在B的b中存在的值,有外键的时候,数据库会自动帮你检查A的b是否在B的b中存在。
1、外建表达的是参照完整性:这是数据固有的,与程序无关。因此,应该交给DBMS来做。
2、使用外建,简单直观,可以直接在数据模型中体现,无论是设计、维护等回有很大的好处,特别是对于分析现有的数据库的好处时非常明显的--前不久我分析了一个企业现有的数据库,里面的参照完整性约束有的是外键描述,有的是用触发器实现,感觉很明显。当然,文档里可能有,但是也可能不全,但是外键就非常明显和直观。
3、既然我们可以用触发器或程序完成的这个工作(指参照完整性约束),DBMS已经提供了手段,为什么我们要自己去做?而且我们做的应该说没有RDBMS做得好。实际上,早期的RDBMS并没有外键,现在都有了,我认为数据库厂商增加这个功能是有道理的。从这个角度来说,外键更方便。
4、关于方便,根据我带项目的情况来看,程序员确实有反映,主要是在调试时输入数据麻烦:如果数据可以违反参照完整性,那么就是说参照完整性本身就不对名誉业务冲突,此时也不应该用触发期货程序实现;否则,说明数据是错误的,根本就不应该进入数据库!而且,这也应该是测试系统的一个内容:阻止非法数据。实际上,前台程序应该对这种提交失败做出处理。数据是企业的而非程序的,储程序要尽量与数据分离,反之亦然。
最后说一下,建键几个原则:
1、 为关联字段创建外键。
2、 所有的键都必须唯一。
3、避免使用复合键。
4、外键总是关联唯一的键字段。
在MySQL 3.23.44版本后,InnoDB引擎类型的表支持了外键约束。
外键的使用条件:
1.两个表必须是InnoDB表,MyISAM表暂时不支持外键(据说以后的版本有可能支持,但至少目前不支持);
2.外键列必须建立了索引,MySQL 4.1.2以后的版本在建立外键时会自动创建索引,但如果在较早的版本则需要显示建立;
3.外键关系的两个表的列必须是数据类型相似,也就是可以相互转换类型的列,比如int和tinyint可以,而int和char则不可以;
外键的好处:可以使得两张表关联,保证数据的一致性和实现一些级联操作;
外键的定义语法:
[CONSTRAINT symbol] FOREIGN KEY [id] (index_col_name, ...)
REFERENCES tbl_name (index_col_name, ...)
[ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}]
[ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT}]
该语法可以在 CREATE TABLE 和 ALTER TABLE 时使用,如果不指定CONSTRAINT symbol,MYSQL会自动生成一个名字。
ON DELETE、ON UPDATE表示事件触发限制,可设参数:
RESTRICT(限制外表中的外键改动)
CASCADE(跟随外键改动)
SET NULL(设空值)
SET DEFAULT(设默认值)
NO ACTION(无动作,默认的)
搞个例子,简单演示一下使用,做dage和xiaodi两个表,大哥表是主键,小弟表是外键:
建表:
1
CREATE
TABLE
`dage` (
2
`id`
int
(
11
)
NOT
NULL
auto_increment,
3
`name`
varchar
(
32
)
default
''
,
4
PRIMARY
KEY
(`id`)
5
) ENGINE
=
InnoDB
DEFAULT
CHARSET
=
latin1;
6
7
CREATE
TABLE
`xiaodi` (
8
`id`
int
(
11
)
NOT
NULL
auto_increment,
9
`dage_id`
int
(
11
)
default
NULL
,
10
`name`
varchar
(
32
)
default
''
,
11
PRIMARY
KEY
(`id`),
12
KEY
`dage_id` (`dage_id`),
13
CONSTRAINT
`xiaodi_ibfk_1`
FOREIGN
KEY
(`dage_id`)
REFERENCES
`dage` (`id`)
14
) ENGINE
=
InnoDB
DEFAULT
CHARSET
=
latin1;
插入个大哥:
1
mysql >
insert
into
dage(name)
values
(
'
铜锣湾
'
);
2
Query OK, 1 row affected (
0.01 sec)
3
mysql >
select
*
from
dage;
4
+
--
--+--------+
5
|
id
|
name
|
6
+
--
--+--------+
7
|
1
|
铜锣湾
|
8
+
--
--+--------+
9
1 row
in
set
(
0.00 sec)
插入个小弟:
1
mysql >
insert
into
xiaodi(dage_id,name)
values
(
1 , '
铜锣湾_小弟A
'
);
2
Query OK, 1 row affected ( 0.02 sec)
3
4
mysql >
select
*
from
xiaodi;
5
+ --
--+---------+--------------+
6
| id
|
dage_id
|
name
|
7
+ --
--+---------+--------------+
8
|
1 |
1 |
铜锣湾_小弟A
|
9
+ --
--+---------+--------------+
把大哥删除:
1
mysql > delete
from
dage
where
id
=
1 ;
2
ERROR 1451 ( 23000 ): Cannot delete
or
update
a parent row: a
foreign
key
constraint
fails (`bstar
/
xiaodi`,
CONSTRAINT
`xiaodi_ibfk_1`
FOREIGN
KEY
(`dage_id`)
REFERENCES
`dage` (`id`))
提示:不行呀,有约束的,大哥下面还有小弟,可不能扔下我们不管呀!
插入一个新的小弟:
1
mysql > insert
into
xiaodi(dage_id,name)
values
(
2 , ' 旺角_小弟A '
);
2
ERROR 1452 ( 23000 ): Cannot add or
update
a child row: a
foreign
key
constraint
fails (`bstar
/
xiaodi`,
CONSTRAINT
`xiaodi_ibfk_1`
FOREIGN
KEY
(`dage_id`)
REFERENCES
`dage` (`id`))
3
提示:小子,想造反呀!你还没大哥呢!
把外键约束增加事件触发限制:
1
mysql > show create table
xiaodi;
2
3
CONSTRAINT `xiaodi_ibfk_1` FOREIGN KEY
(`dage_id`)
REFERENCES
`dage` (`id`)
4
5
mysql > alter table
xiaodi
drop
foreign
key
xiaodi_ibfk_1;
6
Query OK, 1 row affected ( 0.04 sec)
7
Records: 1 Duplicates: 0 Warnings:
8
mysql > alter table
xiaodi
add
foreign
key
(dage_id)
references
dage(id)
on
delete
cascade
on
update
cascade
;
9
Query OK, 1 row affected ( 0.04 sec)
10
Records: 1 Duplicates: 0 Warnings: 0
再次试着把大哥删了:
1
mysql > delete from dage
where
id
=
1 ;
2
Query OK, 1 row affected ( 0.01 sec)
3
4
mysql > select *
from
dage;
5
Empty set ( 0.01 sec)
6
7
mysql > select *
from
xiaodi;
8
Empty set ( 0.00 sec)
得,这回对应的小弟也没了,没办法,谁让你跟我on delete cascade了呢!
例子说明的应该蛮清楚了吧,其他功能对应手册自己实践吧!:-)