如何使用sql server执行更新前触发器?

如何使用sql server执行更新前触发器?,sql,sql-server,database,triggers,sql-server-express,Sql,Sql Server,Database,Triggers,Sql Server Express,我正在使用SQLServerExpress,在更新触发器之前无法执行。还有其他方法可以做到这一点吗?T-SQL只支持AFTER而不是triggers,它没有像其他一些RDBMS中那样的BEFORE触发器 我相信您会希望使用替代触发器。SQL Server中的所有“正常”触发器都是“AFTER…”触发器。没有“之前…”触发器 要在更新之前执行某些操作,请签出。MSSQL不支持之前的触发器。最接近的是而不是触发器,但它们的行为与MySQL中触发器之前的不同 您可以了解更多关于它们的信息,并注意到而不

我正在使用SQLServerExpress,在更新触发器之前无法执行
。还有其他方法可以做到这一点吗?

T-SQL只支持AFTER而不是triggers,它没有像其他一些RDBMS中那样的BEFORE触发器

我相信您会希望使用替代触发器。

SQL Server中的所有“正常”触发器都是“AFTER…”触发器。没有“之前…”触发器


要在更新之前执行某些操作,请签出。

MSSQL不支持
之前的触发器。最接近的是
而不是
触发器,但它们的行为与MySQL中
触发器之前的
不同

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


相反,您可能希望使用不同的方法来实现您想要实现的目标。

请记住,当您使用instead触发器时,除非您在触发器中明确告诉它,否则它不会提交insert。取而代之的真正含义是这样做而不是像通常那样做,这样就不会发生任何正常的插入操作。

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

要在SQL Server中更新前执行
,我使用了一个技巧。我对记录进行了错误更新(
updatetable SET Field=Field
),这样我就得到了记录的前一个映像。

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

deleted表存储删除和删除期间受影响行的副本 更新语句。在执行删除或更新期间 语句,则从触发器表中删除行并将其传输到 已删除的表

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

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

CREATE TRIGGER <TriggerName> ON <TableName>
AFTER UPDATE
AS
  BEGIN
    INSERT INTO <HistoryTable> ( <columns...>, DateChanged )
    SELECT <columns...>, getdate()
    FROM deleted;
  END;
在上创建触发器
更新后
作为
开始
插入到(,日期已更改)
选择,getdate()
从删除;
结束;
我的示例基于以下示例:

完整示例:

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

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

举个例子

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

这是对我有用的答案;删除的表保留原始值;插入的表保存新的/更新的值。可以在更新后使用。删除的表在DELETE和UPDATE语句期间存储受影响行的副本。插入的表在INSERT和UPDATE语句期间存储受影响行的副本。更新事务类似于先删除后插入的操作;旧的行首先复制到已删除的表中,然后新行复制到触发器表和插入的表中。如果不是晚了7年就好了。;-)这应该是正确的答案。这应该作为对现有答案的评论,而不是答案本身。我不确定当OP要求“之前”更新时,这一回答是否相关。从我的观点来看,您可能需要“之前”更新有两个原因触发器:a)停止操作b)在数据更改之前对其进行处理,从而可能丢失数据。对于a)您最好使用不同的方法,如存储过程中的一致性测试。对于b)你可以使用提供的代码-至少这是我所做的,也是我为什么在这个话题上绊倒的原因。比较一下2012年5月3日Luciano的答案