逻辑数据库设计 - 无视约束(谈外键)

  有一些开发人员不推荐使用完整性约束,你可能听过以下这么几点不使用外键的原因。

  1、数据更新有可能和约束冲突。

  2、当前的数据库设计如此灵活,以致于不支持引用完整性约束。

  3、数据库为外键建立的索引会影响性能。

  4、当前使用的数据库不支持外键。

  5、定义外键的语法并不简单,还需要查阅。

一、反模式:无视约束

  即使第一感觉告诉你,省略外键约束能使得数据库设计更加简单、灵活,或者执行更加高效,你还是不得不在其他方面付出相应的代价 -- 必须增加额外的代码来手动维护引用完整性。

  1、完整性问题

  很多人对引用完整性的解决方案是通过编写特定的程序代码来确保数据间的关系的。每次插入新记录时,需要确保外键列所引用的值在其对应的表中存在;每次删除记录时,需要确保所有相关的表都要同时合理地更新。

  为了避免在没有外键约束的情况下产生引用的不完整状态,需要在任何改变生效前执行额外的select查询,以此来确保这些改变不会导致引用错误。

  比如,在插入一条记录前之前,需要检查对应的被引用记录是否存在:

select Account_Id from Account where Account_Id = 1

  然后才能执行Insert操作。

  要删除一条记录,需要先确认没有别的记录引用了该条记录:

select bug_id from Bugs where reported_by = 1

  然后才能执行Delete操作。

  如果发生一个万一情况,这个Account_Id恰巧在删除操作的查询和删除语句的执行间隙插入了一条新的缺陷记录,这该怎么办?

  2、级联问题

  另外很多开发人员避免使用外键约束的理由,是因为这些约束会使得更新多张表中相关联的列变得比较麻烦。比如删除一条被其他记录依赖的数据时,不得不删除所有的子记录来避免违反外键约束:

  delete from Account where RoleId = 1
  delete from Role RoleId = 1

  另外还有update

  update Role set RoleId = 2  update Account set Role = 2 where RoleId = 1

  说白了就是级联更新与级联删除有麻烦,因此干脆不用外键。

  如果有人说的话,听起来像下面的意思,那么他们可能使用了本文所描述的反模式。

  1、我要怎么写这个查询语句来检查一个值是否没有同时在两张表中存在。

  通常这样的需要是为了查找那些孤立的行,那些被遗忘的数据记录行。

  2、有没有一种简单的方法来判断在一张表中存在的数据是否也在第二张表中存在?

  这么做是用来确认父记录确实存在,外键会自动完成这些,并且外键会使用附表的索引尽可能搞笑地完成。

  3、外键?有人告诉我别用它,因为那会影响数据库的效率。

  性能总是用来裁剪设计的一个很好的理由,但总是会引入更多的问题,甚至包括性能问题本身。我之前就看到过,说增加外键 增删改的速度会变慢的说法。但请记住,这种说法只适用于这张表是用于大规模增删改的情况。对于一张主要就是用来大范围增删改的表,不用外键似乎无可厚非。但是如果一张表,增删改并不多,这种说法就不成立了。相反,你避免了外键,却不得不使用更多的手段去维护数据完整性。

  另外,大多数数据库都提供了级联更新与级联删除的功能。这个功能相信初学者都有所耳闻了。实际上,之前本文写代码的时,即使使用了级联更新与删除,但都是不放心,仍然在程序中,按照没有级联的情况,先执行一遍。对于此,我只想对自己说,既然使用了级联功能,就相信它。如果你不相信它,还要自己写代码级联。那就别用它。而事实上,我发现数据库的级联功能,比自己写代码维护要可靠得多。

  对于开销方面,的确对增删改需要那么一点额外的系统开销,但是同时另一方面赚会来的有:

  1、不需要在更新或删除记录前执行select进行检查。

  2、在同步修改时不需要再锁住整张表。

  3、不再需要执行定期的监控脚本来修正不可避免的垃圾数据,孤立数据。

  外键是一个使用很方便的东西,提高性能,还能帮助你在任何简单或复杂的形式的数据变更下始终维持引用完整性。

  总结:客观的分析,本人还是建议使用外键。

时间: 2024-11-08 12:25:27

逻辑数据库设计 - 无视约束(谈外键)的相关文章

逻辑数据库设计 - 需要ID(谈主键Id)

本文的目标就是要确认那些使用了主键,却混淆了主键的本质而造成的一种反模式. 一.确立主键规范 每个了解数据库设计的人都知道,主键对于一张表来说是一个很重要,甚至必需的部分.这确实是事实,主键是好的数据库设计的一部分.主键是数据库确保数据行在整张表唯一性的保障.它是定位到一条记录并且确保不会重复存储的逻辑机制.主键也同时可以被外键引用来建立表与表之间的关系. 难点是选择那一列作为主键.大多数表中的每个属性值都有可能被很多行使用.例如姓名,电子邮件地址等等都不能保证不会重复. 在这样的表中,需要引入

[转帖]数据库,傻逼才用外键约束!

数据库,傻逼才用外键约束! 作者:孤独烟 来自:打杂的ZRJ 引言 其实这个话题是老生常谈,很多人在工作中确实也不会使用外键.包括在阿里的JAVA规范中也有下面这一条 [强制]不得使用外键与级联,一切外键概念必须在应用层解决. 但是呢,询问他们原因,大多是这么回答的 每次做DELETE 或者UPDATE都必须考虑外键约束,会导致开发的时候很痛苦,测试数据极为不方便. 坦白说,这么说也是对的.但是呢,不够全面,所以开一文来详细说明. 正文 首先我们明确一点,外键约束是一种约束,这个约束的存在,会保

逻辑数据库设计 - 单纯的树(递归关系数据)(转)

逻辑数据库设计 - 单纯的树(递归关系数据) 相信有过开发经验的朋友都曾碰到过这样一个需求.假设你正在为一个新闻网站开发一个评论功能,读者可以评论原文甚至相互回复. 这个需求并不简单,相互回复会导致无限多的分支,无限多的祖先-后代关系.这是一种典型的递归关系数据. 对于这个问题,以下给出几个解决方案,各位客观可斟酌后选择. 一.邻接表:依赖父节点 邻接表的方案如下(仅仅说明问题): CREATE TABLE Comments( CommentId int PK, ParentId int, --

2-16 MySQL字段约束-索引-外键

一:字段修饰符 1:null和not null修饰符 我们通过这个例子来看看 mysql> create table worker(id int not null,name varchar(8) not null,pass varchar(20) not null); mysql> insert into worker values(1,'HA','123456'); mysql> insert into worker values(1,'LB',null); ERROR 1048 (2

2-13-MySQL字段约束-索引-外键

高版本导出报错问题,是由于高版本对导出文件优化了权限设置, show variables like '%secure%';查看权限是NULL就代表禁止导出 在配置文件my.cnf [mysqld]下加secure_file_priv=指定导出目录 本节所讲内容: 1.  字段修饰符 2.  清空表记录 3.  索引 4.  外键 5.     视图 一:字段修饰符 (约束) 1:null和not null修饰符 我们通过这个例子来看看 mysql> create table worker(id

MyEclipse数据库教程:表、外键和索引的使用方法

MyEclipse数据库教程:表.外键和索引的使用方法 MyEclipse的数据库资源管理器工具提供了大量的向导和操作,来轻松地创建和删除表.关系和索引.在本教程中,你将学习到: 创建和删除表 创建和删除外键 创建和删除索引 没有MyEclipse?立即下载 1. 创建一个新的索引 创建索引是开发人员重要的性能工具,典型的就是在DBMS上创建一个表的索引键.然而可能在其他领域中经常需要使用ORDER BY或WHERE子句来增强性能.假设您可能在CITY中有很多订购的客户,您可以在该领域中创建索引

数据库多表关系(外键)

数据库多表关系(外键) 字段操作 create table tf1( id int primary key auto_increment, x int, y int ); # 修改 alter table tf1 modify x char(4) default ''; alter table tf1 change y m char(4) default ''; # 增加 mysql>: alter table 表名 add 字段名 类型[(长度) 约束]; # 末尾 eg>: alter t

Android数据库SQLite表内设置外键

Android数据库SQLite表内设置外键 介绍 Android默认的数据是SQLite,但SQLite3.6.19之前(在2.2版本中使用的是3.6.22,因此如果你的应用只兼容到2.2版本就可以放心使用外键功能)是不支持外键的,如果有两张表需要关联,用外键是最省事的,但不支持的话怎么办呢?这里就有一个解决办法,就是用事务将两张表关联起来,并且最后生成一张视图. 现有两张表 Employees Dept 视图 ViewEmps:显示雇员信息和他所在的部门 创建数据库 自定义一个辅助类继承SQ

19、约束之间的比较:主键约束、联合约束、唯一约束、外键约束

约束之间的比较:主键约束.联合约束.唯一约束.外键约束 1.主键约束,primary_key 能唯一确定一张表中的记录,也就是我们通过给某个字段添加约束,就可以使得改字段不重复且不为空. create table test1( id int primary key, name varchar(20) not null ); 1.2.联合约束,只要联合的主键值加起来不重复就可以了,且不为空 create table test2( id int, name varchar(20), password