过去18个月,我们一直致力于开发复杂的数据库和客户端界面。我们定期为此应用程序添加新功能,现在我们所有办公室(包括站点和海外)每天都有数十名用户使用它。这只是告诉你它是一个带有REAL数据库的REAL应用程序。
到目前为止,我们仍然没有编写任何存储过程,除了临时解决客户端版本和更新的数据库模型之间的小问题(旧客户端版本将无法正确更新新创建的字段,直到每个人安装最新版本。)
同样,我们仍然不需要任何触发器。事实上,唯一的SP和触发器是系统的,或者是为复制目的而添加的。
我有一种奇怪的感觉,当开发人员认为数据库优化必须反对数据库规范化时,SP和触发器主要用于补偿数据库设计默认值和/或试图绕过数据库设计规则。
问题是这些工具非常耗时(无论是开发还是维护)。然后每个开发人员都应该非常小心地使用它们,请记住它们是在数据库中维护的最“昂贵”的项目。
我们是否可以认为数据库中没有或很少存储过程/触发器是其正常化级别和/或代码维护成本的良好指示?
编辑:
有些人为使用触发器和SP提供了公平的参数。但我一直认为 大部分时间 这些工具都是以不正当或过度的方式使用的。设置了多少个触发器来在表字段之间进行一些奇特的更新,或者重新计算总计或其他聚合数据?有多少SP用于构建用于报告问题的临时表?这些是开发人员使用这些工具的许多情况中的两个,我认为这通常说明了数据库设计/规范化缺陷。
其他一些人承认应严格控制SP和触发器的使用。我发现它也是必要的。
我必须承认,我正在努力寻找一些坚持不懈的论点,所有这些在我们的其他数据库上工作的SQL极客都看不起我们,告诉他们的朋友“你知道吗?他们甚至不使用SP和触发器!哈哈! “
答案 0 :(得分:12)
我们是否可以认为数据库中没有或几乎没有存储过程/触发器可以很好地表明其规范化水平和/或代码维护成本?
不,你不能。
规范化和存储过程彼此完全分离。
我对SP的看法是数据库与使用它的人之间的抽象层。
强制人们使用SP代替直接CRUD操作,这样可以更容易地更改表格的设计而不会破坏它们。
答案 1 :(得分:12)
存储过程和触发器是工具 - 在数据库管理系统中使用的非常具体的工具。
触发器有很多用途,大大简化了 history 表的维护(其中每一行代表主表的过去一段时间)将ETL请求排队到数据仓库(取决于具体的RDBMS)
无论是从应用程序还是从SQL命令行工具调用存储过程,它们都有它们的位置。
包含存储过程或触发器实际上与规范化或“数据库设计默认值”无关。它们在应用程序中的使用通常直接与应用程序的其他要求相关,可扩展性,可靠性,复制或其他要求可以通过使用这些工具最有效地满足。
如果你不需要他们,请不要使用他们。但是,不要认为触发器或存储过程的存在表明设计不佳。
答案 2 :(得分:5)
除了在代码中遇到大量内联SQL之外,没有什么比这更容易了。至少使用Stored Proc,您可以对其进行语法检查,甚至执行它以查看问题所在。更不用说它会比保存执行计划时在DB上发出查询更快。我一直认为数据库代码属于数据库,但这只是我的观点。
触发器有它们的用途。它们并不总是最好的,但肯定是有原因的。
答案 3 :(得分:5)
至于存储过程,我们不要忘记安全问题。允许应用程序运行内联SQL意味着您的用户帐户需要对所有表进行直接读取,插入,更新和删除访问。如果存在违规行为,则会泄露您的数据库。
触发器有它们的位置。特别是在有许多数据库开发人员可能会或可能不知道(例如)我们保留预算信息变更历史记录的SOX要求的环境中。
答案 4 :(得分:2)
没有。存储过程和触发器以多种不同方式使用。这取决于具体情况,开发人员等。例如,存储过程通常用作安全机制。
我认为唯一适合使用触发器的地方是重构数据库。所以也许你正在谈论这一点。但其他人可能会以其他方式使用它们。
答案 5 :(得分:2)
如何从数据库中获取数据?你构建SQL字符串并执行它们?如果是这样,您如何验证条目是否会破坏数据库?存储过程有助于大大降低风险,因为文本由服务器作为文本处理,而不是作为命令处理。
存储过程通常比对数据库执行SQL字符串要快得多,这也意味着您不必为不同的信息组编写不同的选择,因为它可以由存储过程完成。从程序中抽象数据库的能力也是一些好处,已经提出了几次。
最后,我实际上只使用触发器进行数据库审计(在SQL2005之前没有内置审计功能),这会使用每个更改的prev值和新值更新表。
规范化和优化与存储过程或触发器无关,规范化和优化可能会影响您抽象数据库所需的数量,但每次进行数据库更改时都必须重构代码,这在我看来会比使用存储过程
答案 6 :(得分:2)
“设置了多少个触发器来在表格字段之间进行一些奇特的更新,或者重新计算总计或其他汇总数据?”
使用触发器根据业务规则执行复杂更新不是一个缺陷。这是首选方法。如果要保持数据完整性,应在数据库级别强制执行所有业务规则。除了用户界面之外,还有其他方法可以影响数据库中的数据,无论使用何种方法,业务规则都应该适用。这样导入的数据必须遵循规则,新功能必须遵循规则(而不是必须记住有规则并找到您为强制执行而构建的功能),人们从查询工具批量更新数据(认为提高所有价格10%)必须遵守规则等。
如果您没有单独的报告数据库,则会重新计算报告的速度。当财务运行需要数小时运行的季度报告时,您是想减慢或锁定整个数据库,因为他们必须计算数百万条记录的总数?或者您希望每次更改数据需要更长的时间吗?这通常是一种方法,仅在数据库变大时才使用,并且在它变得足够大以至于具有单独的报告数据库的成本合理之前。因此,是的,这是一个临时的权宜之计,但是当你从原始设计转移到新设计时,这对于保持业务运行是非常必要的(构建OLAP需要相当长的一段时间和不同的技能)数据库)。
答案 7 :(得分:1)
这是一个SP绝对必需的例子:用户界面只是整个应用程序的一小部分。当整个过程独立于用户发生时。 例如,我从一个涉及大量数据处理的项目,从许多不同的来源工作。所以我们收到这些文件,然后我们只运行一个脚本Shell,它将简单地启动一个SP来导入文件中的所有数据,检查它们,操纵它们等等...... 你猜怎么着?用户也可以从用户界面使用同样的SP,而无需再次重写整个数据处理查询!
当然,如果那些处理查询只是简单的SELECT,那么你可以争论SP的必要性,但是当你需要更新数十个表,计算字段,清除数据,清理数据时,那么SP就很幸运了。它并不意味着我们的数据库缺乏规范化,但是当你每天处理数十亿个数据时,并非一切都很简单。
答案 8 :(得分:1)
我们有一个我正在工作的程序,我认为这是触发器的一个很好的案例,因为现在有大约8个不同的版本(API和许多版本的前端和后端)。如果我想改变它处理某些东西的方式,那么如果它是在触发器中而不是必须在8个以上不同的代码库中进行完全相同的更改(具有不同级别的意大利面条编码)会更容易和命名不好的变量)。
答案 9 :(得分:0)
如果您有七个不同的应用程序都与用户数据库交谈,那么使用名为“createUser”的存储过程而不是七个不同的应用程序自己构建INSERT语句会不会更有意义?
现在,新的应用程序必须将用户添加到此数据库,但它有一个新的要求,并且需要添加一个新字段,默认值是从存储在完全不同的第三方中的值填充的应用程序的数据库。
现在,你冷静地改变那七个应用程序,加上新的应用程序,与第三方应用程序交谈以获取值,同时构建INSERT语句。
或者,您可以修改用户数据库的createUser proc以查找来自第三方数据库的数据作为默认值,因此您的其他程序都不需要更改和重新部署,因为它们并不真正关心该值...尚未。
或者,您可以在更新users表时向用户数据库添加触发器,以从第三方数据库中获取该值。
存储过程还具有编译的优点,因此比常规语句更快。
存储过程还可以将单个复杂的sql语句拆分为几个更简单的语句,以提高查询运行的速度。
当数据需求发生变化时,修改存储过程要比更新1000个应用程序的安装要简单得多。
我的$ .02
PS。 多年来我没有在应用程序中编写一行sql。这一切都在存储过程中。它是一个简单的选择,插入,更新,复杂报告或更新,它实际上是应用程序中的单个对象,但存储在数据库中的7个不同表中。