数据库中应该有多少业务逻辑?

时间:2009-07-26 11:56:47

标签: database

我正在开发一个多用户应用程序,它使用(postgresql-)数据库来存储其数据。我想知道我应该将多少逻辑转移到数据库中?

e.g。当用户要保存他刚刚输入的一些数据时。应用程序是否应该将数据发送到数据库,数据库是否确定数据是否有效?或者应用程序应该是行中的智能部分并检查数据是否正常?

在我工作的最后一个(商业)项目中,数据库非常倾倒。没有约束,没有视图等,一切都由应用程序统治。我认为这非常糟糕,因为每次在代码中加入某个表时,都会有相同的代码来检查访问是否一遍又一遍地重复访问。

通过将逻辑转移到数据库中(包含函数,triger和约束),我认为我们可以在应用程序中保存大量代码(以及许多潜在的错误)。但我担心将大部分业务逻辑放入数据库将是一个回旋镖,有一天它将无法维护。

是否有一些现实生活中批准的指南可供使用?

11 个答案:

答案 0 :(得分:13)

如果您不需要大量的分布式可扩展性(想想拥有亚马逊或Facebook等流量的公司)那么关系数据库模型可能足以满足您的性能需求。在这种情况下,使用具有主键,外键,约束和事务的关系模型可以更容易地维护数据完整性,并减少需要完成的协调量(并且一旦您停止使用任何协调,请相信我)在这些事情上,你需要和解 - 即使你和他们你可能会因为错误而来。)

但是,大多数验证代码比C#,Java,Python等语言更容易编写,而不是像SQL这样的语言,因为这是他们设计的类型。这包括验证字符串格式,字段之间的依赖关系等等。所以我倾向于在“普通”代码而不是数据库中执行此操作。

这意味着实用的解决方案(当然也就是我们使用的解决方案)是在有意义的地方编写代码。让数据库处理数据完整性,因为它是擅长的,并让“正常”代码处理数据有效性,因为这是它擅长的。你会发现一大堆不合适的情况,以及在不同的地方做事情的意义,所以要务实,并根据具体情况进行权衡。

答案 1 :(得分:3)

我发现你需要在前端(GUI客户端,如果你有一个或服务器)验证数据库。

数据库可以轻松地声明空值,外键约束等,即数据是正确的形状并正确链接。事务将强制执行原子写入。数据库负责以正确的形状包含/返回数据。

服务器可以执行更复杂的验证(例如,这看起来像电子邮件,看起来像邮政编码等),然后重新构造输入以插入数据库(例如,将其标准化并创建适当的实体插入表格。)

您强调验证的地方在某种程度上取决于您的申请。例如在GUI客户端验证(比方说)邮政编码并立即提供反馈非常有用,但如果您的数据库被其他应用程序(例如应用程序用于批量加载地址)使用,那么数据库周围的图层也需要验证。有时您最终会在两个不同的实现中提供验证(例如,在上面,可能是Javascript前端和Java DAO后端)。我从来没有找到一个好的战略解决方案。

答案 2 :(得分:3)

两分钱:如果你选择聪明,请记住不要进入“太聪明”的领域。数据库不应该处理不适合其数据理解水平的不一致性。

示例:假设您要在字段中插入有效(使用确认邮件检查)电子邮件地址。数据库可以检查电子邮件是否实际符合给定的正则表达式,但要求数据库检查电子邮件地址是否有效(例如,检查域是否存在,发送电子邮件和处理响应)这有点太多了。

这不是一个真实案例。只是为了说明一个智能数据库无论如何都有智能限制,如果一个不存在的电子邮件地址进入它,数据仍然无效,但对于数据库是好的。与OSI模型一样,一切都应该在理解水平上处理数据。以太网并不关心它是否正在传输ICMP,TCP,如果它们是否有效。

答案 3 :(得分:1)

使用关系数据库的常用功能,如主键和外键约束,数据类型声明等是很有意义的。如果您不打算使用它们,为什么还要使用关系数据库呢?

也就是说,所有数据应该在它到达db之前验证类型和业务规则。类型验证只是防御性编程 - 假设用户出去攻击你,然后你会得到更少的不愉快的惊喜。业务规则就是您的应用程序的全部内容。如果您将它们作为数据库结构的一部分,它们将更加紧密地绑定到您的应用程序的工作方式。如果将它们放在应用程序层中,则在业务需求发生变化时更容易更改它们。

作为次要考虑因素:客户通常不太了解他们使用哪个数据库(postgresql,mysql,Oracle等),而不是他们可用的应用程序语言。因此,如果您的应用程序很有可能安装在许多不同的系统上,那么最好的办法是确保您的SQL尽可能标准化。这可能意味着构建与语言无关的数据库功能(如触发器等)将比在应用程序层中放置相同的逻辑更麻烦。

答案 4 :(得分:1)

这取决于应用程序:)

对于某些应用程序,哑数据库是最好的。例如,Google的应用程序运行在一个甚至无法连接的大型哑数据库上,因为需要惊人的可扩展性才能为数百万用户提供服务。

另一方面,对于某些内部企业应用程序而言,使用非常智能的数据库可能是有益的,因为这些数据库通常不仅仅用于应用程序,因此您需要一个单一的控制点 - 想想员工数据库。

如果您的新应用程序与前一个应用程序类似,那么我会使用哑数据库。为了消除所有手动检查和数据库访问代码,我建议使用 ORM 库,例如 Hibernate for Java。它实质上会使您的数据访问层自动化,但会将所有逻辑留给您的应用程序。

关于验证,必须在所有级别上进行。有关详细信息,请参阅其他答案。

答案 5 :(得分:1)

另一个考虑因素是部署。我们有一个应用程序,对于远程安装,数据库更改的部署实际上更容易,而不是实际的代码库。出于这个原因,我们在存储过程和数据库函数中添加了许多应用程序代码。

部署不是您的首要考虑因素,但它可以在决定b / t各种选择方面发挥重要作用

答案 6 :(得分:1)

这是一个人的问题,因为它是一个技术问题。如果你的应用程序是唯一一个操纵数据的应用程序(很少就是这种情况,即使你认为这是计划),并且你只需要提供应用程序编码器,那么一定要保留所有的逻辑申请。

另一方面,如果您有可以处理它的DBA,或者您知道多个应用程序需要验证其访问权限,那么在数据库中实际管理数据非常有意义。

但请记住,数据库验证的最佳方法是:a)数据的类型和b)关系约束,任何自称为RDBMS的东西都应该有一个句柄。

如果您的应用程序代码中有任何事务,那么也应该问自己是否应该将它们作为存储过程推送到数据库,这样就不可能在其他地方错误地重新实现它们。

我知道商店允许数据库访问的唯一权限是通过存储过程,因此DBA对数据存储语义和访问限制都有完全的责任,其他任何人都必须通过他们的网关。这有明显的优势,特别是如果多个应用程序必须能够访问数据。你走得那么远取决于你,但这是一个非常有效的方法。

答案 7 :(得分:1)

虽然我认为大多数数据都应该从用户界面验证(为什么要通过网络发送已知的坏东西来占用资源?),我也认为不对数据库施加约束是不负责任的,因为用户界面不太可能成为数据进入数据库的唯一方式。数据还来自导入,其他应用程序,针对在查询窗口运行的问题的快速脚本修复,批量更新运行(例如,将所有价格更新10%)。我希望所有不良记录都被拒绝,无论它们的来源是什么,数据库是唯一可以确保将会发生的地方。要跳过数据库完整性检查,因为用户界面确实是为了保证您最有可能最终出现数据完整性问题,然后所有数据都变得毫无意义和无用。

答案 8 :(得分:0)

  

e.g。当用户要保存一些时   他刚输入的数据。应该的   应用程序只是将数据发送到   数据库和数据库决定是否   数据有效吗?或者应该   应用程序是智能的一部分   并检查数据是否正常?

最好在前端和服务器端进行验证。因此,如果数据无效,将立即通知用户。否则他将不得不等待数据库回复后回复。

当涉及安全性时,最好在两端验证。前端以及DB。或者DB如何信任应用程序发送的所有数据; - )

答案 9 :(得分:-1)

验证应该在客户端和服务器端完成,一旦有效,就应该存储它。

数据库应该做的唯一工作是任何查询逻辑。因此,更新行,插入行,选择以及其他所有内容都应由服务器端逻辑处理,因为应用程序的真正内容就在那里。

正确构造插件将处理任何外键约束。让业务逻辑调用sproc将以正确的格式插入数据。我并不认真考虑这种验证,但有些人可能会这样做。

答案 10 :(得分:-2)

我的决定是:永远不要在数据库中使用存储过程。存储过程不可移植。