触发器与约束的性能注意事项

时间:2008-09-29 09:47:57

标签: database-design triggers constraints

我试图找出是否应该在数据库内部的触发器或约束中使用业务关键逻辑 到目前为止,我已经在触发器中添加了逻辑,因为它让我可以控制接下来发生的事情,这意味着我可以提供自定义用户消息,而不是可能会混淆用户的错误。

使用约束优于触发器是否有任何明显的性能提升,以及确定使用哪些优先实践的最佳做法。

12 个答案:

答案 0 :(得分:15)

限制约束!

  • 使用约束,您可以指定关系原则,即有关数据的事实。除非某些事实发生变化(即新要求),否则您永远不需要更改约束。

  • 使用触发器指定如何处理数据(插入,更新等)。这是一种“非关系型”的做事方式。

通过类比来更好地解释自己:编写SQL查询的正确方法是指定“你想要的”而不是“如何获得它” - 让RDBMS找出最适合你的方法。这同样适用于此:如果你使用触发器,你必须记住各种事情,如执行顺序,级联等等......如果可能的话,让SQL为你做限制。

这并不是说触发器没有用途。他们这样做:有时您不能使用约束来指定有关数据的某些事实。这是非常罕见的。如果您发现很多,那么架构可能存在一些问题。

答案 1 :(得分:13)

最佳实践:如果您可以使用约束来执行此操作,请使用约束。

触发器并没有那么糟糕(如果正确使用的话),尽管我总是会尽可能地使用约束。 在现代RDMS中,触发器的性能开销与约束相当(当然,这并不意味着某人无法在触发器中放置可怕的代码!)。

偶尔有必要使用触发器来强制执行“复杂”约束,例如想要强制执行一个并且只填充一个表的两个外键字段中的一个(我在几个域中看到过这种情况)型号)。

关于业务逻辑应该驻留在应用程序而不是数据库中的争论在某种程度上取决于环境;如果您有许多应用程序访问数据库,则约束和触发器都可以作为数据正确的最终保护。

答案 2 :(得分:7)

触发器可能会成为性能问题。大约在同一时间,它们也成为维护的噩梦。您无法弄清楚正在发生的情况(奖励!)应用程序与“虚假”数据问题的行为不一致。 [真的,它们会触发问题。]

没有最终用户直接接触SQL。他们使用应用程序。应用程序包含的业务逻辑比触发器更智能,更易于维护。将应用程序逻辑放在应用程序中。将数据放入数据库。

除非您和您的“用户”不共享共同语言,否则您可以向他们解释违规行为。替代方案 - 不解释 - 将一个简单的数据库变成一个问题,因为它将数据和应用程序代码混合成一个不可维护的泥潭。

“我如何绝对保证每个人都正确使用数据模型?”

两种(半)技术。

  1. 确保模型正确:它与实际问题域匹配。没有黑客或变通方法或快捷方式,只能通过复杂的挥手解释,存储过程和触发器进行整理。

  2. 帮助定义应用程序的业务模型层。每个人共享和重用的应用程序代码层。

    一个。此外,请确保模型层满足人们的需求。如果模型层具有正确的方法和集合,那么绕过它以获得对底层数据的直接访问的动机就会减少。一般来说,如果模型是正确的,这不是一个深刻的问题。

  3. 触发器是一种等待发生的火车残骸。约束不是。

答案 3 :(得分:7)

除了使用约束的其他原因之外,Oracle优化器可以使用约束来实现它的优势。

例如,如果您有一个约束(Amount >= 0),然后使用WHERE (Amount = -5)进行查询,Oracle会立即知道没有匹配的行。

答案 4 :(得分:5)

约束和触发器适用于两种不同的事物。约束用于约束数据的域(有效输入)。例如,SSN将存储为char(9),但约束为[0-9] [0-9] [0-9] [0-9] [0-9] [0-9] [ 0-9] [0-9] [0-9](全数字)。

触发器是一种在数据库中实施业务逻辑的方法。再次采用SSN,或许每当SSN发生变化时都需要维护审计线索 - 这将通过触发器来完成,

通常,现代RDBMS中的数据完整性问题可以通过约束的某些变体来处理。但是,您有时会遇到这样的情况:不正确的规范化(或更改的要求,导致现在不正确的规范化)会阻止约束。在这种情况下,触发器可能能够强制执行您的约束 - 但它对RDBMS是不透明的,这意味着它不能用于优化。它也是“隐藏”的逻辑,可能是一个维护问题。决定是否重构模式或使用触发器是一个判断调用。

答案 5 :(得分:4)

一般来说,我更喜欢约束,我的代码会捕获sql server错误并向用户呈现更友好的内容。

答案 6 :(得分:3)

@onedaywhen

您可以在SQL Server中将查询作为约束,只需将其置于标量函数中即可:http://www.eggheadcafe.com/software/aspnet/30056435/check-contraints-and-tsql.aspx

答案 7 :(得分:2)

如果可能的话,使用约束。他们往往更快。触发器应该用于约束无法处理的复杂逻辑。触发器写入也很棘手,如果你发现你必须编写一个触发器,请确保使用基于set的语句,因为triigers对整个插入操作,更新或删除(是的,有时会有多个记录受到影响,计划在那!),而不是一次只有一个记录。如果可以避免,请不要在触发器中使用光标。

是否将逻辑放在应用程序中而不是触发器或约束。不要那样做!!!是的,应用程序在发送数据之前应该进行检查,但数据完整性和业务逻辑必须处于数据库级别,否则当多个应用程序挂钩时,当全局插入完成在应用程序之外时,您的数据将变得混乱。完整性是数据库的关键,必须在数据库级别强制执行。

答案 8 :(得分:2)

@Mark Brackett:“约束用于约束域......触发器是一种强制执行业务逻辑的方式”:在SQL Server中并不是那么简单,因为它的约束功能是有限的,例如:尚未完整的SQL-92。在时态数据库表中采用有序“主键”的经典示例:理想情况下,我使用带有子查询的CHECK约束来防止同一实体的重叠周期,但SQL Server不能这样做,所以我必须使用触发。 SQL Server中缺少的是SQL-92延迟检查约束的能力,但是它们(实际上)在每个SQL语句之后都被检查,因此可能需要一个触发器来解决SQL Server的限制。

答案 9 :(得分:1)

@Meff:使用函数的方法存在潜在问题,因为简单地说,SQL Server CHECK约束是以单行作为工作单元设计的,并且在处理结果集时存在缺陷。有关详细信息,请参阅:[http://blogs.conchango.com/davidportas/archive/2007/02/19/Trouble-with-CHECK-Constraints.aspx][1]

[1]:David Portas的博客:CHECK约束的麻烦。

答案 10 :(得分:1)

与Skliwz相同。 只是为了让您知道规范使用触发器是审计表。如果许多过程更新/插入/删除您要审核的表(谁修改了什么和何时),则触发是最简单的方法。一种方法是简单地在表中添加一个标志(具有一些unicity约束的活动/非活动)并在审计表中插入一些内容。

如果您希望表不保存历史数据,另一种方法是复制审计表中的前一行......

许多人有很多方法可以做到这一点。但有一件事是肯定的,你必须为这个表中的每个更新/插入/删除执行插入

为了避免在不同地方写入插入内容,您可以使用触发器。

答案 11 :(得分:0)

我同意所有人的约束。尽可能多地使用它们。

过度使用触发器的趋势,尤其是新开发人员。我已经看到触发器触发另一个触发器的情况,该触发器触发另一个重复第一个触发器的触发器,创建一个连接服务器的级联触发器。这是触发器的非最佳用户; o)

话虽如此,触发器有它们的位置,应该在适当时使用。它们特别适合跟踪数据的变化(正如Mark Brackett所提到的)。您需要回答“将业务逻辑放在哪里最有意义”的问题?大多数时候我认为它属于代码,但你必须保持开放的心态。