使用触发器来强制执行数据完整性 - 冗余?

时间:2013-12-29 13:06:39

标签: sql-server database-design

我有一个常见的数据库设计问题。

我在数据库中有一个表,其中某个字段在插入时应始终具有值0。将此字段更改为0以外的任何值都涉及某些操作,并且这些操作通过更新触发器强制执行。没有强制执行适当业务规则的0值记录是无用的数据。

我正在考虑在insert上创建一个替代触发器,强制你不能用0以外的任何值将记录插入到这个表中。这不是必需的,因为用户只能通过存储来访问数据库procs,唯一的INSERT proc当前将此值设置为默认值,即0。这也不是安全措施,因为在我们的系统中只有SA是特权用户,并且如果用户以某种方式获取SA密码,他们可以无论如何都要做他们想做的事。

我能想到的唯一用途就是确保即使在将来,没有开发人员可能会意外地允许在不碰到触发器的情况下将值插入到该字段中,这实际上是一个测试工具。

DBA如何处理这样的事情?您是否有特定于测试系统的触发器和约束,而不是部署到生产服务器?您是否将这些触发器留在生产服务器上,作为强制执行完整性的额外措施?

2 个答案:

答案 0 :(得分:2)

我会担心增加一层支票。

如果您设计了系统,以便所有插入和更新都通过存储过程,那么您说“存在一个发生逻辑和数据完整性检查的地方”。如果您开始将检查分散到几段代码中,那么就存在混淆的风险。哪些检查进入触发器?哪些检查进入存储过程?当逻辑应该存储在存储过程中时,为什么会出现触发?

我承认这是一个模糊的边界。约束的使用意味着数据库正在进行一些检查。但是,这些内置于语言中,因此任何合理的开发人员都应该能够轻松理解它们。在这种情况下,请将列的默认值设置为0,以便在表定义中明确说明它应该最初具有此值。

我喜欢在存储过程中包装插入/更新/删除,特别是允许其他检查和日志记录。另一方面是将存储过程强制为 only 接口来修改表。您可以通过只有一个能够修改数据的用户,并让存储过程在进行更改时模拟该用户来强制执行此操作。

答案 1 :(得分:1)

通过触发器强制执行状态机是一种合理的策略。触发器可以访问旧值和新值,并确保“新行必须为0”,“0可以转换为1或2,但不是3”等等...基本上,触发器确保您无法进行转换对你的状态机无效。

这可以作为存储过程之上的“断言”的附加层,实际决定要进行哪种转换。这种触发因素也往往非常便宜,因此没有理由将它们排除在生产之外。

在你的情况下这一切是否合理取决于你的状态机有多复杂 - 它越复杂,这个策略就越合理。