mysql foreign外键详细使用方法和使用事项

  本来这么简单的一个功能,不想写个小总结的,但这个mysql 不能用TAB键确实头大,目前也没装第三方的支持tab程序

  当然对于初学者来说,mysql很多命令行除了查询语名较难外

  还有两个难点就是输写的顺序格式和使用场合.所以这里做一个详细的引用总结.

------------首先简单介绍下外键作用

外键的用(这里我用例子来说明了):

 表A(编号不能重复)

名字编号
张三    0001
张四0002

表B(只有表A编号里出现过的记录才能在表B编号里出现,当表A编号记录进行删除或更新时,表B的对应编号记录也随之改变)

编号资金出入
0002+100
0001-200

从上面表可以看到他们进行关联后的作用了,当然后面联动删除或更新是可选项.

也就是说,在表B中添加个外键和A表关联后,可以有效的控制表B编号记录和A表的编号记录保持完整性,在B表添加记录时,只要表A中编号不存在,B表的编号是写不进去的.会报错,这就是设键的主要作用.

主要有下面四种模式:

  • 1、cascade:从父表删除或者更新且自动删除或更新子表中匹配的行

  • 2、set null:从父表删除或更新行,并设置子表中的外键行为null,如果使用该选项,必须保证子表列没有指定not null

  • 3、restrict:拒绝对父表的删除或更新操作。

  • 4、no action:标准SQL的关键字,在mysql中于restrict相

使用外键的前提:

  1. 表储存引擎必须是innodb,否则创建的外键无约束效果。

  2. 外键的列类型必须与父表的主键类型完全一致。

  3. 外键的名字不能重复(一般使用。

建外键表两种方式(创建表时关联/添加外键)

1) 第一种方式创建表时加外键使用实例:

mysql> create table A( name char(12), id int(8) ,index(id))engine=innodb;                         //先建立A表,


mysql> create table B(                                                                                                                       //建立B表,同时做外键
    -> id int(9),
    -> money int(9),
    -> index(id),
    -> foreign  key(id)  references  A (id)                     //这个是必加项,foreign key(B表要关联的字段),references A表名 (对应字段)
    -> on delete cascade on update cascade           //这里是可选项的,只加一项或都不加都可以的,看需求.

    -> )engine=innodb;                                                   //这个必须是innodb类型,并且和A表的一致


第二方式在已有的表上做和A表关联的外键(最好是新建好没有记录的,不然会因为记录对不上而创建不成功)

mysql> create table C(                                                               //这里先创建一个空表C
    -> id int(7),
    -> money int(5),
    -> index(id)

    -> )engine=innodb;

mysql> alter table Cadd constraint abc                                  //在C表上添加和表A关联的外键,constraint  外键名(自己任意取)
    -> foreign key(id) references A(id)                                       //和创建时一样的输入

    -> on delete cascade on update cascade;                         //一样是可选项,这行不写也可以通过.

注: @以上的cascade是上面介强的四种模式之一,是可以替换成其它模式的,如写成on update set null

       @还可以同时做两个外键,如写成foreign key(id,money) references A(id,money) 即可 

       @两张表关联字段名可以取不一样名字,但类型必须一致

---以下是上面无说明的代码,可以直接复制粘贴调用

create table A( name char(12), id int(8) ,index(id))engine=innodb;   

create table B(id int(9),money int(9),index(id),foreign  key(id)  references  A (id)   on delete cascade on update cascade )engine=innodb;       

--------------------------------

create table C( id int(7),money int(5),index(id) )engine=innodb;

alter table C add constraint abc  foreign key(id) references A(id)  on delete cascade on update cascade;    

2)查看和删除外键(下面命令直接复制可用)

show create table B;   

//先查看外键名, B改成自己表名即可,找到 CONSTRAINT `B_ibfk_1`这项,这里abc就是这个表B的外键名

alter table B drop foreign key B_ibfk_1;

//这样就可以删除外键了.


 ----希望对大家有所帮助.  我的mysql版本是5.7.17          

  


----------------下面都是其它大神的一些谈论摘要,在哪些场合来使用外键(性能和方便间的选择)

最后说一下,建键几个原则:

1、 为关联字段创建外键。

2、 所有的键都必须唯一。

3、避免使用复合键。

4、外键总是关联唯一的键字段。


我的观点是,外键在初始阶段能加的都加上,只有迫不得已的时候才disable或drop掉。遇到性能瓶颈的时候,尽量采用其它方式调优,而不要轻易牺牲掉外键。有外键约束的时候,写程序的确会有约束,但从直觉上说这种约束一定程度上揭示了设计或实现上不合理的地方。带着外键写出来的应用更倾向于严谨。产品上线之前如果确实需要通过牺牲外键达到性能上的优化,再捡相对不重要的外键废弃掉,同时要把这个document下来,下次遇到数据不一致问题的时候,是个线索。两点说明:1. 我们在做的一个项目确实是小项目。 2. 我得承认我最近三年开发都不用关系型数据库,貌似 no sql那么nb的key-value pair存数据,其实这三年在持久层上很多纠结。如果我说的不对,请指正!

下面引用一些有见地的想法:

× 支持外键的:

1. 你的程序再严谨也有可能出现BUG;你自己判断不如交给数据库判断,它做得又快又好。
大多数人的程序没有考虑并发问题。一旦考虑了就得手工加锁,效率很低。
数据可能绕过你的应用程序进入数据库。
2. 性能问题:难道你自己做就没有开销?
一个外键判断分摊到事务级别,开销可以忽略,用户完全没有察觉。
如果是批量导入数据,可以先暂时屏蔽外键,事后用NOVALIDATE选项快速恢复,前提是你的数据是干净的。

也有人提到了如果100张表可能需要建立300个约束,导致性能太差。
我要说的仍然是,是否这300个外键约束都是业务必须的,如果是,没有办法这就是必须要加的,如果不是,那么大可不必在所有的地方都增加外键。
如果在程序中仅对其中的5、6张表的10来个外键约束进行判断,然后和数据库中的300个外键去比较,并评价Oracle的外键性能太差,恐怕是有失公允的。

× 反对外键的:

的确外键在大系统中用的很少,在开发初级,设计数据库的时候一般会加入外键,以保证系统设计的完整性和业务需求的完整性,也便于开发人员了解业务规则,在程序中加以控制,很多大系统在系统稳定后,会逐步将外键去掉,以保证性能,将太多的功能强加于数据库,虽然说数据库很强大,但是毕竟很多人不信任数据库的能强大到什么都能干的地步。所以在一个大系统中外键见的少也不足为奇,小系统就无所谓了,用不用外键取决于设计人员,这样的系统也随处可见。

另引用一篇:

引自http://blog.csdn.net/neusoft_lkz/archive/2009/07/21/4366668.aspx

数据库设计是否需要外键。这里有两个问题:一个是如何保证数据库数据的完整性和一致性;二是第一条对性能的影响。
正方观点:
1,由数据库自身保证数据一致性,完整性,更可靠,因为程序很难100%保证数据的完整性,而用外键即使在数据库服务器当机或者出现其他问题的时候,也能够最大限度的保证数据的一致性和完整性。
eg:数据库和应用是一对多的关系,A应用会维护他那部分数据的完整性,系统一变大时,增加了B应用,A和B两个应用也许是不同的开发团队来做的。他们如何协调保证数据的完整性,而且一年以后如果又增加了C应用呢? 
2,有主外键的数据库设计可以增加ER图的可读性,这点在数据库设计时非常重要。
3,外键在一定程度上说明的业务逻辑,会使设计周到具体全面。
反方观点:
1,可以用触发器或应用程序保证数据的完整性
2,过分强调或者说使用主键/外键会平添开发难度,导致表过多等问题
3,不用外键时数据管理简单,操作方便,性能高(导入导出等操作,在insert, update, delete 数据的时候更快)
eg:在海量的数据库中想都不要去想外键,试想,一个程序每天要insert数百万条记录,当存在外键约束的时候,每次要去扫描此记录是否合格,一般还不止一个字段有外键,这样扫描的数量是成级数的增长!我的一个程序入库在3个小时做完,如果加上外键,需要28个小时!

结论:
1. 在大型系统中(性能要求不高,安全要求高),使用外键;在大型系统中(性能要求高,安全自己控制),不用外键;小系统随便,最好用外键。
2. 用外键要适当,不能过分追求
3. 不用外键而用程序控制数据一致性和完整性时,应该写一层来保证,然后个个应用通过这个层来访问数据库。

4.不管是否加外键,一定要索引。


数据库中主键和外键的设计原则

http://www.cnblogs.com/tianyamoon/archive/2008/04/02/1134394.html

主键和外键是把多个表组织为一个有效的关系数据库的粘合剂。主键和外键的设计对物理数据库的性能和可用性都有着决定性的影响。

必须将数据库模式从理论上的逻辑设计转换为实际的物理设计。而主键和外键的结构是这个设计过程的症结所在。一旦将所设计的数据库用于了生产环境,就很难对这些键进行修改,所以在开发阶段就设计好主键和外键就是非常必要和值得的。

主键:

关系数据库依赖于主键---它是数据库物理模式的基石。主键在物理层面上只有两个用途:

1. 惟一地标识一行。

2. 作为一个可以被外键有效引用的对象。

基于以上这两个用途,下面给出了我在设计物理层面的主键时所遵循的一些原则:

1. 主键应当是对用户没有意义的。如果用户看到了一个表示多对多关系的连接表中的数据,并抱怨它没有什么用处,那就证明它的主键设计地很好。

2. 主键应该是单列的,以便提高连接和筛选操作的效率。

注:使用复合键的人通常有两个理由为自己开脱,而这两个理由都是错误的。其一是主键应当具有实际意义,然而,让主键具有意义只不过是给人为地破坏数据库提供了方便。其二是利用这种方法可以在描述多对多关系的连接表中使用两个外部键来作为主键,我也反对这种做法,理由是:复合主键常常导致不良的外键,即当连接表成为另一个从表的主表,而依据上面的第二种方法成为这个表主键的一部分,然,这个表又有可能再成为其它从表的主表,其主键又有可能成了其它从表主键的一部分,如此传递下去,越靠后的从表,其主键将会包含越多的列了。

3. 永远也不要更新主键。实际上,因为主键除了惟一地标识一行之外,再没有其他的用途了,所以也就没有理由去对它更新。如果主键需要更新,则说明主键应对用户无意义的原则被违反了。

注:这项原则对于那些经常需要在数据转换或多数据库合并时进行数据整理的数据并不适用。

4. 主键不应包含动态变化的数据,如时间戳、创建时间列、修改时间列等。

5. 主键应当有计算机自动生成。如果由人来对主键的创建进行干预,就会使它带有除了惟一标识一行以外的意义。一旦越过这个界限,就可能产生认为修改主键的动机,这样,这种系统用来链接记录行、管理记录行的关键手段就会落入不了解数据库设计的人的手中。




文章来源: mysql foreign外键详细使用方法和使用事项

人吐槽 人点赞

猜你喜欢

发表评论

用户名: 密码:
验证码: 匿名发表

你可以使用这些语言

查看评论:mysql foreign外键详细使用方法和使用事项