`
乡村里的一条土狗
  • 浏览: 69486 次
  • 性别: Icon_minigender_1
  • 来自: 北京
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

数据库约束:使用它们还是放弃它们?

阅读更多

 

作者简介:
Frank Sommers is president of Autospaces. He also is a Senior Editor with Artima Developer.

 

概述

关系型数据库提供了丰富的特性来保证数据的完整性。然而,除了常用的设计规范,很少有企业应用利用这些功能特性,相反,他们倾向于在应用层里实现对数据完整性的检查。如果sql数据约束有价值的话,为什么那么多应用不使用它呢?

 

关于数据管理,有一个很重要的趋势,特别是在Web应用上,人们乐于使用弱SQL模式 或者是完全避免忽略关系数据的一些基本原则。在Artima最近一个讨论是关于“NoSQL”运动的,跟以前一样 通常的讨论结果基本认为数据库关系约束很有用处,开发者需要自己去承担不使用约束带来的后果。

 

这显而易见,规范的关系数据模型存在之初就是为了保证数据的完整性的。用户通常会认为数据库是一个有保障的数据来源:它为我们常用的数据查询提供了一个基本的概念,就像SQL查询,它返回的数据就是一种“正确无误”的数据。但如果你把关系约束给禁掉了,把大部分的数据完整性维护放在应用层的代码里,那对这种“正确无误”的保证是很困难的。

很多的关于NoSQL的讨论都是围绕着反数据库标准的问题 弱化SQL规范会导致脏数据的产生 现代数据管理制度,比如这个SQL标准,提供了很多额外的机制去确保数据的完整性。在细读了最新版的 Joe Celko's  SQL for Smarties 被高度推荐的一本书 它让我明白应该用最少的SQL功能来保证数据的完整性。例如,我建表时从来不用SQL检查机制,我也不使用其它的标准SQL工具,为的就是让数据库更加干净。

 

尽管我很相信尽量使用数据管理系统的诸多好处,我还是倾向于在domain和controller层的代码里实现数据完整性相关的操作。当然,所有的代码都需要认真的测试。最近我统计了为数不少的我用   ScalaTest  写成的测试套件,大概有上百个测试用例,我发现有不低于30%的测试用例会要求在应用层强制检查数据完整约束。举个例子,测试用例会检查 API-level 的前提条件 比如,检查null值是否被正确的处理。如果一个复杂的对象被当作一个方法的参数,我会写代码测试这个方法能否在这个复杂对象参数状态异常时正常处理。

 

我一直这样做,即使是在实体层使用了 Hibernate Validator 、认真的声明了  entity classes  里需要校验的约束条件。最后,我们好要认真的在表现层 对于我,这里是Flex 写大量的数据完整性检查代码去确保用户提交有效的数据到server端API里。表现层的代码也有测试用例。总之,由于此,我们在实体层、表现层、数据层编码来确保数据完整性,同时在测试用例里相当的一部分都用在覆盖对控制层、表现层的完整性检查。

 

这样会有大量的代码直接违反DRY原则。我所知道的对非冗余数据完整性校验最有好感的程序是在 ActiveRecord , Rails' O/R mapping and persistence layer. ActiveRecord 在实体层类里声明完整性约束。 Rail 的控制层和表现层使用这些数据资料可以在数据有问题时向用户显示友好的错误信息。然而,跟 Hibernate Validator 相比, ActiveRecord 很少使用数据库丰富的底层提供的功能:这两个框架生成的约束性的sql语句几乎对外键和 non-null 域的声明有所保留,而其他的约束检查是在某种校验层实现的(部分约束在实体类里)。

 

我想,在一个较为理想的方案里,数据库应该对数据有保护作用,包括强制约束。这种效果我们也可以通过写大量的SQL来实现,但这不会是个很合适的方法,因为大多数的SQL数据库都依赖于SQL错误码来指示约束异常。例如,设置一个约束,salsry 字段不能接受小于5000或者大于100000的数据,当用户试图插入一个100的薪水值时数据库会返回一个错误码 但这个错误码很难被转换成应用中其它层中可以使用的信息。我们不去这样做是因为这样做的价值很小,特别是这种转换在不同的数据库之间还不能兼容。

 

你认为什么地方是最合适的定义数据约束的地方呢?你是否同意SQL应该提供更多的标准错误码来提示数据违法约束条件呢?

 

外刊IT评论  

28
4
分享到:
评论
13 楼 zhouzhao21 2009-10-26  
ivy1107 写道
简单的说,就是,
function function1{
……
function2(a,b);
……
}

function function2(a, b){
……
}

是在function1中验证参数a,b是否合法。还是在function2中验证a,b是否合法。


两个都验证或至少要验证面向外部的函数。
12 楼 ivy1107 2009-10-05  
简单的说,就是,
function function1{
……
function2(a,b);
……
}

function function2(a, b){
……
}

是在function1中验证参数a,b是否合法。还是在function2中验证a,b是否合法。
11 楼 whaosoft 2009-09-30  
我感觉还是别放弃吧
10 楼 fandayrockworld 2009-09-29  
有公认的缺陷,以后必定会有牛的公司或组织出相应的解决方案!用Java Web举例子,如: 开始我们用jsp+servlet,感觉层次不分明,于是有了strus;我们感觉每次用jdbc方式操作数据库太繁琐,于是有了hibernate;我们感觉程序模式不科学,于是有了spring(可能spring初衷不是这个,请大家斧正)。
如果你是一个大牛,那么就赶紧把你认为程序流程中有缺陷的步骤仔细的想一下,自己研究,或许你就是下一个流行框架的盘古。
9 楼 kkppccdd 2009-09-29  
如果数据源只被一个应用使用,约束做在哪里都一样。但如果数据源会被多个应手使用(或以后应用层更新或干脆更换了个应用层),数据库的约束就很关键了。
8 楼 dotaking 2009-09-29  
我反对

je补丁
7 楼 giginet 2009-09-28  
从来就不用外键,也很少用。有的时候直接去后台删除一条数据,用外键真的好麻烦,尤其是关联很多的情况下。
6 楼 yantoba 2009-09-27  
虽然我未曾参加过火星圈的讨论
不过我也是一直保留主键,去除外键
5 楼 RockyWoo 2009-09-27  
bupolongyi 写道
我在做的建设银行的项目.. 就完全放弃的外键约束
很不懂这么做的必要性... 因为我觉得如果没有约束 数据完整性就缺失了
不过这系统甚至已经跑了4年了.. 从项目初期到现在新加的子项目 所有的表结构
都没有使用外键关联,在一对一 或者一对多的表中.. 只是添加了一方的某个唯一字段 而不是ID.. 比如说部门表下有 ID属性 和部门编号 都是唯一的.. 然后在多方用部门编号表示一对多的关系..但没有使用外键.. 这么搞到底有什么好处?

我大概知道你做哪个项目了O(∩_∩)O哈哈~
4 楼 soleghost 2009-09-27  
在业务变化频繁、海量数据库的系统中,数据库底层不适合外键
对于数据的完整性、一致性,可以通过应用层保证
3 楼 bupolongyi 2009-09-27  
我在做的建设银行的项目.. 就完全放弃的外键约束
很不懂这么做的必要性... 因为我觉得如果没有约束 数据完整性就缺失了
不过这系统甚至已经跑了4年了.. 从项目初期到现在新加的子项目 所有的表结构
都没有使用外键关联,在一对一 或者一对多的表中.. 只是添加了一方的某个唯一字段 而不是ID.. 比如说部门表下有 ID属性 和部门编号 都是唯一的.. 然后在多方用部门编号表示一对多的关系..但没有使用外键.. 这么搞到底有什么好处?
2 楼 徐风子 2009-09-27  
看题目是个很“强力”的话题呀。
1 楼 opensdp 2009-09-26  
原文的这个帖子讨论的很厉害

相关推荐

Global site tag (gtag.js) - Google Analytics