55

I'm using Sqlserver express and I can't do before updated trigger. There's a other way to do that?

gbn
  • 422,506
  • 82
  • 585
  • 676
Bigballs
  • 3,729
  • 10
  • 30
  • 27

9 Answers9

50

It is true that there aren't "before triggers" in MSSQL. However, you could still track the changes that were made on the table, by using the "inserted" and "deleted" tables together. When an update causes the trigger to fire, the "inserted" table stores the new values and the "deleted" table stores the old values. Once having this info, you could relatively easy simulate the "before trigger" behaviour.

Stamen
  • 595
  • 4
  • 7
  • 3
    This was the answer that worked for me; the DELETED table holds the original value; the INSERTED table holds the new/updated value. Works fine with AFTER UPDATE. – gimlichael May 19 '15 at 14:34
  • 1
    The deleted table stores copies of the affected rows during DELETE and UPDATE statements. The inserted table stores copies of the affected rows during INSERT and UPDATE statements. An update transaction is similar to a delete operation followed by an insert operation; the old rows are copied to the deleted table first, and then the new rows are copied to the trigger table and to the inserted table. – csmith Dec 09 '16 at 01:44
50

MSSQL does not support BEFORE triggers. The closest you have is INSTEAD OF triggers but their behavior is different to that of BEFORE triggers in MySQL.

SQL Server offers DML triggers

DML triggers is a special type of stored procedure that automatically takes effect when a data manipulation language (DML) event takes place that affects the table or view defined in the trigger (Insert, Update, Delete).

DML trigger statements use two special tables: the deleted and inserted tables.

Note

INSTEAD OF triggers override the standard actions of the triggering statement. Therefore, they can be used to perform error or value checking on one or more columns and perform additional actions before inserting, updating or deleting the row or rows.

From the now offline documentation

Specifies that the trigger is executed instead of the triggering SQL statement, thus overriding the actions of the triggering statements.

You can learn more about types of dml triggers here

Thus, actions on the update may not take place if the trigger is not properly written/handled. Cascading actions are also affected.

You may instead want to use a different approach to what you are trying to achieve.

surfmuggle
  • 5,527
  • 7
  • 48
  • 77
achinda99
  • 5,020
  • 4
  • 34
  • 42
16

Can't be sure if this applied to SQL Server Express, but you can still access the "before" data even if your trigger is happening AFTER the update. You need to read the data from either the deleted or inserted table that is created on the fly when the table is changed. This is essentially what @Stamen says, but I still needed to explore further to understand that (helpful!) answer.

The deleted table stores copies of the affected rows during DELETE and UPDATE statements. During the execution of a DELETE or UPDATE statement, rows are deleted from the trigger table and transferred to the deleted table...

The inserted table stores copies of the affected rows during INSERT and UPDATE statements. During an insert or update transaction, new rows are added to both the inserted table and the trigger table...

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

So you can create your trigger to read data from one of those tables, e.g.

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

My example is based on the one here:

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

Charlie Joynt
  • 4,411
  • 1
  • 24
  • 46
9

T-SQL supports only AFTER and INSTEAD OF triggers, it does not feature a BEFORE trigger, as found in some other RDBMSs.

I believe you will want to use an INSTEAD OF trigger.

Ian Nelson
  • 57,123
  • 20
  • 76
  • 103
4

All "normal" triggers in SQL Server are "AFTER ..." triggers. There are no "BEFORE ..." triggers.

To do something before an update, check out INSTEAD OF UPDATE Triggers.

Tomalak
  • 332,285
  • 67
  • 532
  • 628
2

To do a BEFORE UPDATE in SQL Server I use a trick. I do a false update of the record (UPDATE Table SET Field = Field), in such way I get the previous image of the record.

ThinkingStiff
  • 64,767
  • 30
  • 146
  • 239
Luciano
  • 21
  • 1
2

The updated or deleted values are stored in DELETED. we can get it by the below method in trigger

Full example,

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
Lenin
  • 21
  • 1
1

Full example:

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
Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
Nick Oetjen
  • 129
  • 4
  • I'm not sure how this response is relevant when OP is asking for "Before" update – KMC Jul 25 '19 at 12:04
  • From my point of view there are two reasons why you might want a "Before" trigger: a) Stop the action b) Do something with the data before they are changed and thus might be lost. For a) you'd preferably use a different way like a consistency test in a stored procedure. For b) you can use the offered code - at least this is what I did and why I stumbled over this topic. – Nick Oetjen Jul 26 '19 at 13:18
  • Compare the answer of Luciano May 3rd, 2012 – Nick Oetjen Jul 26 '19 at 13:25
1

Remember that when you use an instead trigger, it will not commit the insert unless you specifically tell it to in the trigger. Instead of really means do this instead of what you normally do, so none of the normal insert actions would happen.

mkj
  • 2,761
  • 5
  • 24
  • 28
HLGEM
  • 94,695
  • 15
  • 113
  • 186