如何使用 sql server 执行 BEFORE UPDATED 触发器?

Posted

技术标签:

【中文标题】如何使用 sql server 执行 BEFORE UPDATED 触发器?【英文标题】:How can I do a BEFORE UPDATED trigger with sql server? 【发布时间】:2010-10-13 04:06:40 【问题描述】:

我正在使用 Sqlserver express,但无法执行 before updated 触发器。还有其他方法吗?

【问题讨论】:

【参考方案1】:

更新或删除的值存储在DELETED中。我们可以在触发器中通过下面的方法得到它

完整示例,

CREATE TRIGGER PRODUCT_UPDATE ON PRODUCTS
FOR UPDATE 
AS
BEGIN
DECLARE @PRODUCT_NAME_OLD VARCHAR(100)
DECLARE @PRODUCT_NAME_NEW VARCHAR(100)

SELECT @PRODUCT_NAME_OLD = product_name from DELETED
SELECT @PRODUCT_NAME_NEW = product_name from INSERTED

END

【讨论】:

【参考方案2】:

完整示例:

CREATE TRIGGER [dbo].[trig_020_Original_010_010_Gamechanger]
   ON  [dbo].[T_Original]
   AFTER UPDATE
AS 
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;
    DECLARE @Old_Gamechanger int;
    DECLARE @New_Gamechanger int;

    -- Insert statements for trigger here
    SELECT @Old_Gamechanger = Gamechanger from DELETED;
    SELECT @New_Gamechanger = Gamechanger from INSERTED;

    IF @Old_Gamechanger != @New_Gamechanger

        BEGIN

            INSERT INTO [dbo].T_History(ChangeDate, Reason, Callcenter_ID, Old_Gamechanger, New_Gamechanger)
            SELECT GETDATE(), 'Time for a change', Callcenter_ID, @Old_Gamechanger, @New_Gamechanger
                FROM deleted
            ;

        END

END

【讨论】:

我不确定当 OP 要求“之前”更新时此响应有何相关性 从我的角度来看,您可能需要“之前”触发器的原因有两个:a) 停止操作 b) 在数据更改之前对数据执行某些操作,因此可能会丢失。对于 a) 您最好使用不同的方式,例如存储过程中的一致性测试。对于 b)您可以使用提供的代码 - 至少这是我所做的,也是我偶然发现这个主题的原因。 比较 Luciano 2012 年 5 月 3 日的答案【参考方案3】:

MSSQL 不支持BEFORE 触发器。您拥有的最接近的是 INSTEAD OF 触发器,但它们的行为与 mysql 中的 BEFORE 触发器不同。

您可以了解更多关于它们的信息here,并注意INSTEAD OF 触发器“指定执行触发器而不是触发 SQL 语句,从而覆盖触发语句的操作。”因此,如果未正确写入/处理触发器,则可能不会发生更新操作。级联操作也会受到影响。

您可能想要使用不同的方法来实现您想要实现的目标。

【讨论】:

【参考方案4】:

请记住,当您使用替代触发器时,除非您在触发器中明确告知它,否则它不会提交插入。而不是真的意味着这样做而不是你通常做的事情,所以不会发生任何正常的插入操作。

【讨论】:

这应该作为对现有答案的评论而不是答案本身。【参考方案5】:

不能确定这是否适用于 SQL Server Express,但即使您的触发器在更新之后发生,您仍然可以访问“之前”数据。您需要从 deletedinserted 表中读取数据,这些表是在更改表时动态创建的。这基本上就是@Stamen 所说的,但我仍然需要进一步探索才能理解这个(有用的!)答案。

deleted 表在 DELETE 和 更新语句。在执行 DELETE 或 UPDATE 期间 语句,行从触发器表中删除并转移到 被删除的表...

inserted 表在 INSERT 期间存储受影响行的副本 和 UPDATE 语句。在插入或更新事务期间,新的 行被添加到插入表和触发器表中...

https://msdn.microsoft.com/en-us/library/ms191300.aspx

因此您可以创建触发器以从其中一个表中读取数据,例如

CREATE TRIGGER <TriggerName> ON <TableName>
AFTER UPDATE
AS
  BEGIN
    INSERT INTO <HistoryTable> ( <columns...>, DateChanged )
    SELECT <columns...>, getdate()
    FROM deleted;
  END;

我的例子是基于这里的:

http://www.seemoredata.com/en/showthread.php?134-Example-of-BEFORE-UPDATE-trigger-in-Sql-Server-good-for-Type-2-dimension-table-updates

sql-servertriggers

【讨论】:

如果不是晚了 7 年就好了。 ;-) 这应该是正确的答案。【参考方案6】:

要在 SQL Server 中执行BEFORE UPDATE,我使用了一个技巧。我错误地更新了记录 (UPDATE Table SET Field = Field),这样我就得到了以前的记录图像。

【讨论】:

【参考方案7】:

MSSQL 中确实没有“前触发器”。但是,您仍然可以通过同时使用“插入”和“删除”表来跟踪对表所做的更改。当更新导致触发器触发时,“插入”表存储新值,“删除”表存储旧值。一旦有了这些信息,您就可以相对容易地模拟“触发前”行为。

【讨论】:

这是对我有用的答案; DELETED 表保存原始值; INSERTED 表保存新的/更新的值。更新后工作正常。 删除的表在 DELETE 和 UPDATE 语句期间存储受影响行的副本。插入的表在 INSERT 和 UPDATE 语句期间存储受影响行的副本。更新事务类似于删除操作后跟插入操作;先将旧行复制到已删除表中,然后将新行复制到触发器表和插入表中。【参考方案8】:

SQL Server 中的所有“正常”触发器都是“AFTER ...”触发器。没有“BEFORE ...”触发器。

要在更新前做点什么,请查看INSTEAD OF UPDATE Triggers。

【讨论】:

【参考方案9】:

T-SQL 仅支持 AFTER 和 INSTEAD OF 触发器,它不具有 BEFORE 触发器,这在其他一些 RDBMS 中可以找到。

我相信您会想要使用 INSTEAD OF 触发器。

【讨论】:

以上是关于如何使用 sql server 执行 BEFORE UPDATED 触发器?的主要内容,如果未能解决你的问题,请参考以下文章

如何查看sql server 2008的SQL语句执行错误日志

SQL SERVER如何远程执行DDL语句?

SQL Server如何固定执行计划

如何查看SQL Server2000执行过的SQL语句

如何在 SQL Server 中使用带有框架的窗口函数执行 COUNT(DISTINCT)

SQL Server 如何执行 带参数的 存储过程