Database design 您应该在数据库级别和应用程序级别实施约束吗?

Database design 您应该在数据库级别和应用程序级别实施约束吗?,database-design,Database Design,我一直在读Dan Chak的《企业Rails》一书,它让我思考:您是否认为您应该在数据库级别和应用程序级别都有数据约束?或者,您是否觉得与RubyonRails这样固执己见的框架类似——数据库只是数据的“哑存储库”,所有检查都应该在您的应用程序中完成(我不想在这里挑出RoR——我自己也是Rails的超级粉丝,但我不同意它处理数据库的方法) 我个人认为,为了确保数据库和应用程序的安全,您应该同时拥有它们。我的意思是,您应该使用非空约束,为字段指定一个已知的长度(而不是将字段全部保留在nvarcha

我一直在读Dan Chak的《企业Rails》一书,它让我思考:您是否认为您应该在数据库级别和应用程序级别都有数据约束?或者,您是否觉得与RubyonRails这样固执己见的框架类似——数据库只是数据的“哑存储库”,所有检查都应该在您的应用程序中完成(我不想在这里挑出RoR——我自己也是Rails的超级粉丝,但我不同意它处理数据库的方法)

我个人认为,为了确保数据库和应用程序的安全,您应该同时拥有它们。我的意思是,您应该使用非空约束,为字段指定一个已知的长度(而不是将字段全部保留在nvarchar(255)),在数据库中设置外键检查约束触发器,然后还可以通过应用程序中的业务逻辑规则来实现这一点。IMO这使得您的应用程序通过其用户界面变得健壮,并且对可能直接访问数据库的人也具有安全性

我最常看到的反论点是,它需要相当于重复逻辑的东西;一次是在数据库级别,一次是在应用程序级别——假设您有一个检查约束来验证是否输入了产品的SKU(即其长度大于零)

您现在还需要在业务逻辑中包含验证方法,以确保用户输入的值的长度大于零,还可能需要一些客户端Javascript来捕获用户输入数据时的错误

我个人并不认为这是一件坏事——是的,您有一些重复的逻辑,但最终的结果是“数据库作为堡垒”的心态,因为如果您考虑一下,您的数据是应用程序中最重要的一部分;毕竟,如果数据很容易被破坏和破坏,那么您闪亮的新Web 2.0应用程序有什么好处


你对此有何看法?这个数据库应该是像诺克斯堡那样无法穿透的堡垒,还是由激光保护的开放式保险箱?换句话说,您是应该牺牲一些逻辑复制来确保数据模型的安全,还是将一切都留给您的应用程序,而仅仅使用数据库来存储数据?

如果您确定永远不会有另一个客户端应用程序,您可以将数据库作为简单的存储来处理。然而,如果您有多个客户机应用程序,那么显然您必须在所有客户机应用程序中复制约束,这是一个坏主意。记住,其他客户机包括开发人员工具


此外,通过将数据库用作“哑存储库”,您很可能会得到效率较低的应用程序。数据库可以比应用程序更高效地完成很多工作。为什么不利用这一点呢?

我认为您应该不惜一切代价保护您的数据。没有什么比尝试报告由于应用程序有错误而具有错误数据的应用程序更糟糕的了。这意味着什么

你应该通过FK来加强你的关系,没有理由不这样做。您应该尽量避免使用空值,并且只在空值合适时使用它们。不过,我确实认为有一条细微的界线


您是否应该解析电话号码以确保其格式正确?可能不会,但是您应该将电话号码存储在一个没有格式问题的模式中

是,如果要限制数据库中的内容。这些层应该尽可能彼此不同,并且您的数据库不应该依赖另一层来确保它遵循规则

无法保证有缺陷(或恶意的)“业务逻辑”层不会将有毒数据插入表中。当然,如果您可以信任其他层,则可能不需要它。但我在一家大型机商店工作,那里的DBA总是不得不修复年轻的Java Whippersnapper在没有充分(任何?)测试的情况下将错误代码发布到生产中所造成的问题:-)


在不同开发区域之间共享的数据库表(对我们来说就是这些)应该始终保护自己不受错误数据的影响。当应用程序A将不可靠的数据放入应用程序B使用的表中时,承受压力的不是应用程序A开发人员,而是DBA。

如果你遵循Jeff Atwood的说法,数据库只是一个愚蠢的数据存储和检索系统,那么你将把所有验证放在应用程序层

然而,我发现应用程序就像小孩子一样。如果不加以制止,他们会把房间里的一切东西都乱扔。要由父母来收拾残局。在这种情况下,将由DBA进行清理

然而,我认为您在使用每个数据库数据完整性特性时都需要小心,因为它确实存在。使用外键约束和触发器重载数据库可能会产生比您想象的更多的问题。我倾向于只在关系非常密切的表上使用外键,例如表头/明细表对。如果你开始在任何地方添加外键,你最终会得到一个不可测量的数据库

我很少使用触发器。我认为他们使数据库非常不透明。您发出一个简单的update/insert/delete命令,可能会发生奇怪的事情。我想有两个地方触发是不可避免的:

  • 当没有应用程序的源代码写入数据库时,需要修改行为。触发器是您唯一的选择

  • 如果要对视图执行CRUD操作。插入/更新/删除操作必须使用触发器

  • 我倾向于在应用程序中执行基本验证。通过这种方式,用户会立即得到反馈,认为有问题。复杂验证