Mysql学习之路06-外键

外键
外键的作用,主要有两个:
一个是让数据库自己通过外键来保证数据的完整性和一致性
对子表的约束:子表进行写操作的时候,如果对应的外键字段在父表找不到对应的匹配,那么操作失败(约束子表数据操作)
对父表的约束:父表数据进行(删和改:都必须涉及到主键本身),如果对应的主键在子表中已经被数据所引用,那么就不允许操作
一个就是能够增加ER图的可读性
一张表可以有多个外键
增加外键
alter table 表名
add [constraint 外键名] foreign key [id] (index_col_name, …)
references 表名 (index_col_name, …)
删除外键:外键不可修改;
alter table 表名 drop foreign key(外键名);

外键条件:
1,外键要存在:首先保证表的存储引擎是innodb,如果不是innodb存储引擎,外键可以创建,但是没有约束效果
2,外键字段的字段类型必须与父表的主键类型完全一致
3,增加外键的字段(数据已经存在),必须保证数据与父表主键要求对应

外键约束:通过对外键的需求,进行定制操作,都是对父表的约束
district:严格模式(默认的),父表不能删除或者更新一个已经被子表数据引用的记录
cascade:级联模式:父表的操作,对应子表关联的数据也跟着操作
set null:置空模式:父表的操作之后,子表对应的数据(外键字段)被置空
语法:foreign key(外键字段)references 父表(主键字段) on delete set null update cascade;

主键和外键是相对于整个数据库来说的,总体来说就是要实现数据库的实体完整性、参照完整性等完整性的约束。并满足数据库规范化的要求 1NF、2NF…
对于一个表定义了一个主键,对于该表可以为通过该键唯一地表示表中的每一记录。外键是相对于表中的一个列给它的一个约束,一般是另一个表中的主键,该列的值必须在另一个表中出现。
由此可见,外键表示了两个关系之间的联系。以另一个关系的外键作主关键字的表被称为主表,具有此外键的表被称为主表的从表。外键又称作外关键字。
外键的作用:
保持数据一致性,完整性,主要目的是控制存储在外键表中的数据。 使两张表形成关联,外键只能引用外表中的列的值!
恩, 好象不缺少一些关系数据库的基础知识.
简单的说, 在关系型数据库中的每一个表都具备这样的特点, 在同一个表中没有完全一致的两行数据, 当一行数据可以有少数几个属性确定的话,这几个属性就可以成为主键, 设立了表的主键之后,数据库系统会为主键的列建立索引和制约, 利用主键进行检索的速度是最快的.
如果有两个表AB, 他们之间存在着某种对应关系,这种关系可以是A中一行记录对应于B中的一行记录,也可以是A的一行记录对应于B的多行记录,还可以是A的多行对应于B的多行,在关系型数据库中, 这种对应关系也要做成关系表,下面就一对一, 一对多, 多对多几种情况来说明一下关系表
一对一
表A(学号, 姓名)
表B(学号, 学习成绩)
表A是一份学生名单, 学号是主键
表B是一份成绩单, 学号也是主键,这样两个表就是一对一的关系, 反映出这一关系的是学号, 如果把表A做为主表的话, 表B的学号就是外键了

一对多
表A(班级, 人数)
表B(学号, 姓名)
表A是一份班级列表, 表B是一分学生名单,每个学生都属于某一个班级, 而一个班级可以有很多学生
为了表示这样的关系, 可以做一个关系表C(学号,班级) 其中,学号是主键, 这就保证了一对多的关系, 而学号和班级, 都是外键, 由于B,C

多对多
表A(课程, 学分)
表B(学号, 姓名)
表A是一份课程表
表B是份名单, 一个学生可以选多门课程,一门课程中也可以有很多学生, 为了反映这样的关系建立表C(课程,学号)其中课程和学号都是主键,这就保证了多对多的关系, 同时他们也是外键

作为外键的属性反映了主表中的某些属性, 因此其类型要和主表的对应属性一致才行
建立了外键之后会产生一致性的制约, 比如说, 在一对多的例子中, 不允许在关系表中出现主表中没有的学号或者是班级,
另外,对外键的更新和删除, 也就有了下面两种制约
- 级联, 当删除了主表的主键之后, 同时也删除关系表中的外键, 比如,删除了一对多的例子中删除了班级, 系统会自动删除关系表C中含有该班级的所有记录
- 制约, 只有当关系表中没有与该主键对应的外键时才允许删除该主键,再比如, 在一对多的例子中, 想删除某一班级的话,就必须先删除关系表C中所有含该班级的记录

外键的设立可以保证数据的对应关系避免因为错误操作而遭到破坏,同时, 外键也可以提示系统事先建立索引和结合操作的执行计划,从而提高结合计算的效率
  例如:
  a b 两个表
  a表中存有客户号,客户名称
  b表中存有每订个客户的单
  有了外键后
  你只能在确信b 表中没有客户x的订单后,才可以在a表中删除客户x
  建立外键的前提: 本表的列必须与外键类型相同(外键必须是外表主键)。
  指定主键关键字: foreign key(列名)
  引用外键关键字: references <外键表名>(外键列名)(被参考的表)
  事件触发限制: on delete和on update ,可设参数cascade(跟随外键改动), restrict(限制外表中的外键改动),set Null(设空值),set Default(设默认值),[默认]no action
  例如:
  outTable表 主键 id类型 int
  创建含有外键的表:
  create table temp(
  id int,
  name char(20),
  foreign key(id) references outTable(id) on delete cascade on update cascade);
  说明:把id列 设为外键 参照外表outTable的id列 当外键的值删除 本表中对应的列筛除 当外键的值改变 本表中对应的列值改变。
  建键几个原则:
  1、 为关联字段创建外键。
  2、 所有的键都必须唯一。
  3、避免使用复合键。
4、外键总是关联唯一的键字段。
在关系中所有表中具有相同含义的字段作为公共部分来连接不同表中的记录。外键可以是一对一的,一个表的记录只能与另一个表的一条记录连接,或者是一 对多的,一个表的记录与另一个表的多条记录连接。
MySQL中“键”和“索引”的定义相同, 所以外键和主键一样也是索引的一种。不同的是MySQL会自动为所有表的主键进行索引,但是外键字段必须由用户进行明确的索引。这和一些封建思想比较沉重的家庭是一样的,外来的孩子(儿媳妇,倒插门女婿)一般都是不受重视的。
表间一对一关系示例:
有两张表,第一张表是记录公司有多少人,都有谁,也就是员工编号及员工姓名这些基本表。另一张表记录每个月发给用户多少工资,所谓工资表是也。
但是工资表里面不能以员工姓名为主键,同样要通过员工id,因为员工的姓名是可能重复的啊。部门经理叫张三,小弟也叫张三,那这俩张三的工资能一样吗?并且员工表里面的每个人都有工资,否则谁也不给你干活,且一个人只能有一份工资,否则老板也不同意了。所以员工表和工资表是通过员工id进行关联的一 对一关系。
/建立员工表/
create table employees (
id int(5) not null auto_increment ,
name varchar(8) not null,
primary key (id)
)
type=innodb;
/*
建立工资表
*/
create table payroll(
id int(5) not null,
emp_id int(5) not null,
name varchar(8) not null,
payroll float(4,2) not null,
primary key(id),
index emp_id (emp_id),
foreign key (emp_id) references employees (id)
)
type = innodb;
参照完整性:
当外键与另一个表的字段有关系,而且这种关系是惟一时,这个系统就称为处于参照完整性的状态。也就是说,如果一个字段在所有的表中只出现一次,而且每个表的这个字段的变化都会影响其他表,这就是存在参照完整性。
术语理解上可能不太方便,其实就是说要在有外键的表中保持所有数据的一致性。比如说“张三”离职了,在员工表里面肯定没有这个人了,可是如果在工资表里面还存在这个孩子,那么老大就会很生气的。
MySQL的外键只能在InnoDB表中使用:
MySQL对此一直持观望态度,它允许使用外键,但是为了完整性检验的目的,在除了InnoDB表类型之外的所有表类型中都忽略了这个功能。这可能有些怪异,实际上却非常正常:对于数据库的所有外键的每次插入、更新和删除后,进行完整性检查是一个耗费时间和资源的过程,它可能影响性能,特别是当处理 复杂的或者是缠绕的连接树时。因而,用户可以在表的基础上,选择适合于特定需求的最好结合。。
所以,如果需要更好的性能,并且不需要完整性检查,可以选择使用MyISAM表类型,如果想要在MySQL中根据参照完整性来建立表并且希望在此基 础上保持良好的性能,最好选择表结构为innoDB类型。
MySQL创建外键语法:
创建外键的语法是这样的:FOREIGN KEY (当前表的字段名)… REFERENCES参照表 (参照表的字段名)
foreign key (emp_id) references employees (id);的意思就是说当前表的emp_id字段是以employees的id字段为外键的。
注意事项:
关系中的所有表必须是innoDB表,在非InnoDB表中,MySQL将会忽略FOREIGN KEY…REFERENCES修饰符。
用于外键关系的字段必须在所有的参照表中进行明确地索引,InnoDB不能自动地创建索引。
在外键关系中,字段的数据类型必须相似,这对于大小和符号都必须匹配的整数类型尤其重要。
即使表存在外键约束,MySQL还允许我们删除表,并且不会产生错误(即使这样做可能会破坏更早创建的外键)
删除外键方法:
long long ago,人们只能通过删除表来删除外键。不过现在MySQL(在4.0.13及更高版本中)提供了一种从表中删除外键比较缓和的方法,缓和与否不太清楚,但是至少不再那么无耻。
ALTER TABLE table-name DROP FOREIGN KEY key-id;
这里有一个概念,这个外键的id是啥玩意?我们可以通过SHOW CREATE TABLE 命令来获得key-id的值。日后我们详细讨论这些内容,大家可以自行演示。
/*
显示建表结构语句,key-id为payroll_ibfk_1
*/
show create table payroll \G
/*

   Table: payroll

Create Table: CREATE TABLE payroll (
id int(5) NOT NULL,
emp_id int(5) NOT NULL,
name varchar(8) NOT NULL,
payroll float(4,2) NOT NULL,
PRIMARY KEY (id),
KEY emp_id (emp_id),
CONSTRAINT payroll_ibfk_1 FOREIGN KEY (emp_id) REFERENCES employees (id)
) ENGINE=InnoDB DEFAULT CHARSET=latin1
1 row in set (0.00 sec)
*/
自动键更新和删除:
外键可以保证新插入的记录的完整性。但是,如果在REFERENCES从句中从已命名的表删除记录会怎样?在使用同样的值作为外键的辅助表中会发生什么?
很明显,那些记录也应该被删除,否则在数据库中就会有很多无意义的孤立记录。MySQL可能通过向FOREIGN KEY…REFERENCES修饰符添加一个ON DELETE或ON UPDATE子句简化任务,它告诉了数据库在这种情况如何处理孤立任务。
请注意,通过 ON UPDATE 和ON DELETE规则,设置MySQL能够实现自动操作时,如果键的关系没有设置好,可能会导致严重的数据破坏。例如,如果一系列的表通过外键关系和ON DELETE CASCADE规则连接时,任意一个主表的变化都会导致甚至只和原始删除有一些将要联系的记录在没有警告的情况下被删除。所以,我们在操作之前还是要检查这些规则的,操作之后还要再次检查。

在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(无动作,默认的)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值