最近关于外键的使用很头疼发现这边文章,真是旱苗得甘雨呢,先剽窃过来,谢谢大侠了哈哈
原帖网址:
http://www.javaeye.com/topic/2832
我看到的一些项目中,当数据表之间存在明显的外建约束的情况下,但是数据库的设计却只是简单的在子表中包含一个父表id的字段,而没有任何约束存在,从理论上来说,为保证数据的一致性,是应该加上外建约束的。但是这种情况存不算是少量了,除开mysql不支持外建之外,是否还有隐情?
还有一个问题,就算是使用了外建约束,你们通常使用级连删除或者更新吗?
就是说,是自己手动删除子,然后再删除父;还是直接删除父,让数据库级连来删除子??
我一般都采用先手动删除子,然后删除父。因为我觉得,让数据库级连处理的话,他可能还要分析表之间的约束,才进行删除操作,而这部分分析如果由我来完成的话,可能程序的执行速度会快一些,我是这样想的,不知是否正确。
凤舞凰扬:
做过MIS系统的都知道,一般说来,数据分为两种:基础数据和业务数据。一般说来,业务数据中肯定包含多个基础数据,比如简单地说一张机票数据,它就包括:货币类型、机场、航空公司等多个基础数据,这个时候,如果都要建立FK的话,是没有任何意义的,更不需要去考虑什么级联删除的,结果只有一个,严重影响效率,而且结构凌乱。但是在业务数据中,机票的基本信息和机票的价格构成了一个整体,这个时候如果不使用FK,那么在设计上是个失误,在实现的时候也绝对是个隐患!比如删除的时候,删除了机票,但是留下了机票的价格,大家可以相信,这是多么荒谬的事情。
所以,使不使用FK,关键要区分基础数据和业务数据。
另外,一个好的数据库设计并不是纯粹考虑数据库,而是来源于好的业务建模和对象建模。
首先基础数据的不存在并不能代表业务数据的不存在或者逻辑错误,其次,比如基础数据,是不能随意删除的,当然,我们有很多的控制方法,比如失效等什么的。对于基础数据不用外键是综合各方面考虑的,不是说不能用外键,但是用了外键将导致一个非常可怕的问题,就是数据访问的问题,每访问一个业务数据,那么意味着有可能要join访问10个以上的表,效率会严重降低。
好的数据库设计不能是没有一点冗余,或者说严格符合关系要求,因为实际的应用是面向对象的,在将面向对象的数据转换为面向关系的数据时,是需要这样做的。从逻辑上说,一个基础数据的不存在,并不代表什么,比如说,你没有输入一个国家或者删除一个国家,并不代表没有了这个国家。而业务数据就不同了,如果你删除了一张业务数据,那么就代表了该业务数据已经不存在,而此时再存在与之相关的业务数据是不符合逻辑的(比如一个法规作废,那么与之相关的法规就都必须受影响)。
好的数据库设计来自于好的对象设计。
为了更好的理解我的意思,请参看一下业务主键和逻辑主键哪个更好的帖子。
这样说吧,如果你在基础表中用的是逻辑主键,那么,业务表用外键的话,将自然引用的是逻辑值(比如毫无意义的数字或UUID),这样,如果你想查找一个业务表,那么你自然就需要去join更多的表。
你会说,基础表采用业务主键就是。但你有没有想过,一般来说,基础表是不少的,一个业务表同时要引用多个基础表或者多次引用一个基础表,如果真是建立了外键的,那么DBMS维护这个外键都是非常可怕的事情。
我不知道你做数据库的是否会先进行数据模型设计,如果是的话,那么你就可以领略这种恐怖性了!错综复杂的关系将使你数据库的性能,数据模型的清晰性严重降低,同时你的数据结构复杂性大为上升。
一个好的数据库设计不是盲目去追求范式,我们现在所用的数据库全部是关系数据库,而思想应该是面向对象的。将面向对象的思想实现为面向关系的存储。
永远记住一点,好的数据库设计永远都是来自好的对象设计。