4

在过去的 18 个月里,我们一直在研究复杂的数据库和客户端界面。我们会定期向此应用程序添加新功能,现在每天都有数十名用户在我们的所有办公室(包括站点和海外)使用。这只是为了告诉您它是一个带有 REAL 数据库的 REAL 应用程序。

到现在为止,我们仍然不用写任何存储过程,除了临时解决客户端版本和更新数据库模型之间的小问题(旧客户端版本不会正确更新新创建的字段,直到大家安装最新的版本)。

同样,我们仍然不需要任何触发器。事实上,唯一的 SP 和触发器是系统的,或者是为了复制目的而添加的。

当开发人员认为数据库优化必须反对数据库规范化时,我有一种奇怪的感觉,即 SP 和触发器主要用于补偿数据库设计默认值和/或试图绕过数据库设计规则。

问题是这些工具非常耗时(无论是开发还是维护)。然后每个开发人员都应该非常小心地使用它们,记住它们是在数据库中维护的最“昂贵”的项目。

我们是否可以认为在数据库中没有或只有很少的存储过程/触发器是其规范化水平和/或代码维护成本的一个很好的指标?

编辑:

你们中的一些人为使用触发器和 SP 提供了公平的论据。但我一直认为,大多数时候这些工具的使用方式不当或过度。设置了多少触发器来在表字段之间进行一些花哨的更新,或者重新计算总计或其他聚合数据?有多少 SP 用于构建用于报告问题的临时表?这是开发人员使用这些工具的许多情况中的两种,我认为这通常说明数据库设计/规范化缺陷。

其他一些人承认应该严格控制 SP 和触发器的使用。我也觉得很有必要。

我必须承认,我试图找到一些支持的论点,所有这些在我们其他数据库上工作的 SQL 极客都看不起我们,告诉他们的朋友“你知道吗?他们甚至不使用 SP 和触发器!哈哈!”

4

10 回答 10

12

我们是否可以认为在数据库中没有或只有很少的存储过程/触发器是其规范化水平和/或代码维护成本的一个很好的指标?

你不能。

规范化和存储过程是完全分开的。

我对 SP 的看法是数据库和使用它的人之间的抽象层。

强迫人们使用 SP 而不是直接的 CRUD 操作将更容易改变表的设计而不会破坏它们。

于 2008-10-23T11:36:26.637 回答
12

存储过程和触发器是工具——在数据库管理系统中使用的非常具体的工具。

触发器有多种用途,从大大简化历史表的维护(其中每一行代表主表的过去时间段)到将 ETL 请求排队到数据仓库(取决于特定的 RDBMS)

存储过程也有自己的位置,无论它们是从应用程序调用还是从 SQL 命令行工具调用。

包含存储过程或触发器实际上与规范化或“数据库设计默认值”无关。它们在应用程序中的使用通常与应用程序的其他要求直接相关,即可扩展性、可靠性、复制或其他可以通过使用这些工具最有效地满足的要求。

如果您不需要它们,请不要使用它们。但是,不要假设触发器或存储过程的存在表明设计不佳。

于 2008-10-23T11:42:39.400 回答
5

没有什么比在代码中遇到一大堆有 bug 的内联 SQL 更让我讨厌的了。至少使用存储过程,您可以对其进行语法检查,甚至可以执行它以查看问题所在。更不用说当执行计划被保存时,它比仅仅在数据库中触发查询要快。我一直认为数据库代码属于数据库,但这只是我的看法。

触发器有其用途。它们并不总是最好的,但肯定是有原因的。

于 2008-10-23T11:57:06.017 回答
5

至于存储过程,我们不要忘记安全问题。允许应用程序运行内联 SQL 意味着您的用户帐户需要直接读取、插入、更新和删除所有表的访问权限。如果有任何违规行为,您的数据库就会暴露出来。

触发器有它们的位置。尤其是在有很多数据库开发人员可能知道也可能不知道(例如)我们保留预算信息更改历史的 SOX 要求的环境中。

于 2008-10-23T12:28:00.807 回答
2

不可以。存储过程和触发器以许多不同的方式使用。这取决于环境、开发人员等。例如,存储过程通常用作安全机制。

我认为唯一适合使用触发器的地方是重构数据库时。所以也许你在这一点上有所作为。但是其他人可能会以其他方式使用它们。

于 2008-10-23T11:40:11.433 回答
2

如何从数据库中取回数据?你会构建 SQL 字符串并执行它们吗?如果是这样,您如何验证条目不会破坏数据库?存储过程有助于大大降低这种风险,因为服务器将文本作为文本而不是命令进行处理。

存储过程通常比对数据库执行 SQL 字符串快得多,这也意味着您不必为不同的信息组编写不同的选择,因为它都可以由存储过程完成。从程序中抽象出数据库的能力也是一个被提出过几次的好处。

最后,我真的只使用触发器进行数据库审计(在 SQL2005 之前没有内置的审计功能),它将用每次更改的 prev 和新值更新表。

规范化和优化与存储过程或触发器无关,规范化和优化可能会影响您需要多少抽象数据库,但在我看来,每次更改数据库时都必须重构代码比使用存储过程更糟糕

于 2008-10-23T11:50:58.043 回答
2

“设置了多少触发器来在表字段之间进行一些花哨的更新,或者重新计算总计或其他聚合数据?”

使用触发器根据业务规则进行复杂的更新并不是一个缺陷。这是首选方法。如果要维护数据完整性,则应在数据库级别强制执行所有业务规则。除了用户界面之外,还有其他方法可以影响数据库中的数据,无论使用哪种方法,都应该应用业务规则。这样,导入的数据必须遵守规则,新功能必须遵守规则(而不是必须记住有规则并找到您为执行规则而构建的功能),人们从查询工具批量更新数据(认为将所有价格提高 10%)将必须遵守规则等。

如果您没有单独的报告数据库,通常会重新计算总计以提高报告速度。当财务部门运行需要数小时才能运行的季度报告时,您是否想放慢或锁定整个数据库,因为他们必须根据数百万条记录计算总计?还是您宁愿对数据的每次更改都多花一秒钟的时间?这通常是一种仅在数据库变大并且在它变得足够大以证明拥有单独的报告数据库的成本之前才使用的方法。因此,是的,这是一种临时权宜之计,但是当您从原始设计转移到新设计时,这对于保持业务运行是非常必要的(构建 OLAP 需要相当长的时间和一套不同的技能数据库)。

于 2008-10-29T13:35:12.487 回答
1

我们有一个我正在工作的程序,我认为这是一个很好的触发器案例,因为现在有大约 8 个不同的版本(一个 API 和许多版本的前端和后端)。如果我想改变它处理某些东西的方式,如果它在触发器中,而不是必须在 8 个以上不同的代码库中做出完全相同的改变(意大利面条编码的水平不同),这会容易得多和命名不佳的变量)。

于 2009-03-10T03:23:45.657 回答
1

这是一个绝对需要 SP 的示例:用户界面只是整个应用程序的一小部分。并且当整个过程独立于用户发生时。例如,我从事一个项目,该项目涉及来自许多不同来源的大量数据处理。所以我们收到这些文件,然后我们只运行一个脚本外壳,它会简单地启动一个 SP 来导入文件中的所有数据,检查它们,操作它们等等......你猜怎么着?用户也可以从用户界面使用相同的 SP,而无需再次重写整个数据处理查询!

当然,如果那些处理查询只是简单的 SELECT,那么你可以争论 SP 的必要性,但是当你需要 UPDATE 几十张表、计算字段、清除数据、清理数据时,SP 是有福的。这并不意味着我们的数据库缺乏规范化,但是当您每天处理数十亿数据时,并非一切都可以简单。

于 2008-10-29T14:07:28.477 回答
0

如果您有七个不同的应用程序都在与用户数据库通信,那么拥有一个名为“createUser”的存储过程而不是七个不同的应用程序自己构建该 INSERT 语句不是更有意义吗?

现在,一个新应用程序必须将用户添加到此数据库,但它有一个新要求,需要添加一个新字段,即默认值是从存储在完全不同的第 3 方应用程序数据库中的值填充的。

现在,你去改变这七个应用程序,加上新的一个,与第 3 方应用程序对话以获得价值,同时构建 INSERT 语句。

或者,您可以修改用户数据库的 createUser proc 以从 3rd 方数据库中查找数据作为默认值,因此您的其他程序都不需要更改和重新部署,因为它们并不真正关心该值...然而。

或者,您可以在用户表更新时向用户数据库添加触发器,以从第 3 方数据库中获取该值。

存储过程还具有编译的好处,因此比常规语句更快。

存储过程还可以将单个复杂的 sql 语句分解为几个更简单的语句,以提高查询运行的速度。

当数据需求发生变化时,修改存储过程比更新 1000 次安装的应用程序要简单得多。

我的 $.02

附言。多年来我没有在应用程序中编写过一行 sql。这一切都在存储过程中。无论是简单的选择、插入、更新、复杂的报告,还是在应用程序中实际上是单个对象但存储在数据库中的 7 个不同表中的更新。

于 2009-09-14T20:29:25.553 回答