【问题标题】:Alternative to triggers in SQL ServerSQL Server 中触发器的替代方法
【发布时间】:2010-01-15 20:36:22
【问题描述】:

为了消除触发器的潜在问题,可以使用哪些替代方法来获得对 INSERT 操作触发的事件做出反应的相同功能?

我有一个需要在插入时添加一些附加值的数据库。 INSERT 由编译后的代码控制,不能更改。

示例:程序插入一个字符串,我需要从该字符串中为指向查找表的新字段提供一个整数。

如果有触发器的替代方案,请告诉我任何替代方案的利弊。主要原因是我们的数据库标准中不允许使用触发器。

SQL Server 2008 企业版

【问题讨论】:

  • 您能否编辑您的问题以反映您使用的 SQL Server 版本。
  • 您试图通过替代方法来避免哪些“潜在问题”,该方法可以执行触发器的作用?
  • 取决于您需要实现多少逻辑,但您可能会查看默认值和计算列来做简单的事情
  • @Todd Moses:该规则目前会给您带来维护问题。作为开发人员,您的工作是提出解决方案并证明约束何时不合理。这是需要更改或至少规避规则以提供解决方案的情况之一。像这样的规则一开始就不应该存在,因为它们会产生像你现在面临的问题。
  • 一个简单的“避免不必要的触发器”通常对于未来的大多数维护问题来说是一个足够好的指导方针。硬性规定的“从不使用触发器”是一条愚蠢的规则,应该在长期造成更多伤害之前尽快废除。

标签: sql-server triggers


【解决方案1】:

可以使用存储过程、触发器或更复杂的插入语句来替代普通插入。由于您无法控制插入语句,因此您也无法使用存储过程。所以你唯一的选择是触发器。

您所描述的正是触发器存在的原因。如果您需要完成此任务,则无法在您列出的限制条件下完成。

触发器是最好的选择。更改数据库标准(或至少允许此任务成为例外),因为它们存在缺陷。

【讨论】:

  • 我同意但不能更改标准。
  • @Todd Moses:我至少会尝试。但是我明白。即使您可以更改规则,也不会很快完成,以便您在合理的时间内解决手头的问题。
【解决方案2】:

如何根据插入的字符串确定整数?

您可能想要研究的另一种选择是computed columns in SQL Server。如果该匹配是一个非常简单的匹配(例如从字符串中提取字符 10 到 14)或类似的东西,您可以创建一个计算列来自动执行此操作 - 不需要触发器。

您甚至可以使这些计算列持久化(物理存储为表的一部分)并在这些字段上创建索引!

计算列从 SQL Server 2000 开始可用,持久列从 SQL Server 2005 开始。

【讨论】:

  • 字符串中的字符是我可以在 switch 语句中使用的
【解决方案3】:

我知道很久以前有人问过这个问题。在 SQL Server 2008 中引入了“更改数据捕获”MSDN。另一种选择,但仅在 2008 R2 之后有效的是“更改跟踪”Setting up change tracking。虽然您可以查询行以过滤 (look here) 更改的内容,但这可能会或可能不会“解决”触发器的问题。

【讨论】:

    【解决方案4】:

    触发器是在 SQL 表上发生事件(插入、更新、删除)后执行操作的方式;它们存在的事实使得不可能有任何可行的替代方案。不幸的是,但是您所说的数据库标准有效地阻止您做您想做的事情,而无需运行一些定期监视您的表然后执行您需要的操作的进程,或者将您的所有数据库 CrUD 操作更改为通过存储过程来执行您想要的操作。既然你说后者是不可能的——你不能改变 INSERT 语句——那么你就只剩下触发器了。

    【讨论】:

    【解决方案5】:

    SQL Server 2005 现在有一个叫做 OUTPUT 子句的东西,它可以在 INSERT(或其他操作)发生后进行额外的处理。这个article 涵盖了更多细节。例如,如果您需要在 INSERT 命令之后进行处理,您可以执行类似...

    INSERT INTO Contact
    (FirstName, MiddleName, LastName)
    
    OUTPUT INSERTED.ContactID, INSERTED.FirstName, INSERTED.MiddleName, INSERTED.LastName
    INTO Contact_Audit    
    VALUES
    (@@SCOPE_IDENTITY, 'Joe', 'D.', 'Schmoe')
    

    您将拥有为他们创建的唯一 ID。

    【讨论】:

      【解决方案6】:

      如果您想使用数据历史记录,请使用系统版本历史记录表。您不需要显式创建触发器。

      https://docs.microsoft.com/en-us/sql/relational-databases/tables/temporal-tables?view=sql-server-ver15

      【讨论】:

        【解决方案7】:

        您的选择有限。我认为您唯一的其他选择是通过存储过程调用进行插入并将额外代码放入存储过程中。

        【讨论】:

        • OP 公开表示不能修改 INSERT 语句,因为它们在编译代码中。
        【解决方案8】:

        我认为我们现在可以使用休眠事件系统实现触发器,尽管会影响性能。我以前没有这样做过。但我认为它有效

        【讨论】:

        • 问题中没有提到休眠。 OP 说代码已经编译好了。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多