33

I am trying to produce an all-in-one delete/insert/update trigger. I get two "incorrect syntax near AFTER at the second and third AFTERS and a syntax error near the last END.

CREATE TRIGGER trig_all_dml
 ON [dbo.file]
 AFTER UPDATE
 AS BEGIN
    UPDATE 
           (excess code)       
 END

 AFTER INSERT
 AS BEGIN
     UPDATE 
             (excess code)
  END

 AFTER DELETE
 AS BEGIN
    UPDATE (excess code)

  END
  GO

Hopefully, this is enough information. I think the problem is my syntax but I can't find the correct syntax online.

1
  • 3
    Why can't you just have three separate, focused triggers, one for each operation? Think about the Single Responsibility Principle! That'll make maintenance much easier down to road ... Commented Nov 26, 2013 at 6:06

5 Answers 5

87

the am giving you is the code for trigger for INSERT, UPDATE and DELETE this works fine on Microsoft SQL SERVER 2008 and onwards database i am using is Northwind

/* comment section first create a table to keep track of Insert, Delete, Update
create table Emp_Audit(
                    EmpID int,
                    Activity varchar(20),
                    DoneBy varchar(50),
                    Date_Time datetime NOT NULL DEFAULT GETDATE()
                   );

select * from Emp_Audit*/

create trigger Employee_trigger
on Employees
after UPDATE, INSERT, DELETE
as
declare @EmpID int,@user varchar(20), @activity varchar(20);
if exists(SELECT * from inserted) and exists (SELECT * from deleted)
begin
    SET @activity = 'UPDATE';
    SET @user = SYSTEM_USER;
    SELECT @EmpID = EmployeeID from inserted i;
    INSERT into Emp_Audit(EmpID,Activity, DoneBy) values (@EmpID,@activity,@user);
end

If exists (Select * from inserted) and not exists(Select * from deleted)
begin
    SET @activity = 'INSERT';
    SET @user = SYSTEM_USER;
    SELECT @EmpID = EmployeeID from inserted i;
    INSERT into Emp_Audit(EmpID,Activity, DoneBy) values(@EmpID,@activity,@user);
end

If exists(select * from deleted) and not exists(Select * from inserted)
begin 
    SET @activity = 'DELETE';
    SET @user = SYSTEM_USER;
    SELECT @EmpID = EmployeeID from deleted i;
    INSERT into Emp_Audit(EmpID,Activity, DoneBy) values(@EmpID,@activity,@user);
end
Sign up to request clarification or add additional context in comments.

3 Comments

Here U r doing trigger event(Update, delete, insert) i think on two table(inserted, deleted), but I want to do on one table(mytable), how can i do this?
use Select 1 From inserted better than use * for performance.
This code is broken because it assumes that inserted has only a single row. This should not be the accepted answer.
12

I use that for all status (update, insert and delete)

CREATE TRIGGER trg_Insert_Test
ON [dbo].[MyTable]
AFTER UPDATE, INSERT, DELETE 
AS
BEGIN
SET NOCOUNT ON;

DECLARE @Activity  NVARCHAR (50)

-- update
IF EXISTS (SELECT * FROM inserted) AND EXISTS (SELECT * FROM deleted)
BEGIN
    SET @Activity = 'UPDATE'
END

-- insert
IF EXISTS (SELECT * FROM inserted) AND NOT EXISTS(SELECT * FROM deleted)
BEGIN
    SET @Activity = 'INSERT'
END

-- delete
IF EXISTS (SELECT * FROM deleted) AND NOT EXISTS(SELECT * FROM inserted)
BEGIN
    SET @Activity = 'DELETE'
END



-- delete temp table
IF OBJECT_ID('tempdb..#tmpTbl') IS NOT NULL DROP TABLE #tmpTbl

-- get last 1 row
SELECT * INTO #tmpTbl FROM (SELECT TOP 1 * FROM (SELECT * FROM inserted
                                                 UNION 
                                                 SELECT * FROM deleted
                                                 ) AS A ORDER BY A.Date DESC
                            ) AS T


-- try catch
BEGIN TRY 

    INSERT INTO MyTable  (
           [Code]
          ,[Name]
           .....
          ,[Activity])
    SELECT [Code]
          ,[Name]
          ,@Activity 
    FROM #tmpTbl

END TRY BEGIN CATCH END CATCH


-- delete temp table
IF OBJECT_ID('tempdb..#tmpTbl') IS NOT NULL DROP TABLE #tmpTbl

SET NOCOUNT OFF;
END

4 Comments

Thanks !, interesting ... Does this work when multiple records are being updated, deleted in a single transaction / statement ? I will do some testing ! .. I am interested in a single trigger that fires for both update and delete regarding some audit / version record keeping ..
I use this trigger for (insert, update and delete). It works well
great little way of knowing what exactly triggered the trigger. Is it delete, update or an insert!? Thanks!
thats a weird way of adding a change, by doing a union select one of either instered or deleted arbirtray by Date if it has a date column at all. if you select from deleted you are sure to save the old value. if your do two inserts for change you can save both old and new value.
11

Not possible, per MSDN:

You can have the same code execute for multiple trigger types, but the syntax does not allow for multiple code blocks in one trigger:

Trigger on an INSERT, UPDATE, or DELETE statement to a table or view (DML Trigger)

CREATE TRIGGER [ schema_name . ]trigger_name 
ON { table | view } 
[ WITH <dml_trigger_option> [ ,...n ] ]
{ FOR | AFTER | INSTEAD OF } 
{ [ INSERT ] [ , ] [ UPDATE ] [ , ] [ DELETE ] } 
[ NOT FOR REPLICATION ] 
AS { sql_statement  [ ; ] [ ,...n ] | EXTERNAL NAME <method specifier [ ; ] > }

2 Comments

I'm using "IF EXISTS(SELECT * FROM Inserted)", etc.
Sure you can do that - be aware that an update (from a trigger perspective) is treated like a DELETE followed by an INSERT - so the old values will be in DELETED and the updated values will be in INSERTED
0

I agree with @Vishnu's answer. I would like to add that if you want to use the application user in your trigger you can use "context_info" to pass the info to the trigger.

I found following very helpful in doing that: http://jasondentler.com/blog/2010/01/exploiting-context_info-for-fun-and-audit

1 Comment

The URL above doesn't seem to work with the trailing "/". Try this instead: jasondentler.com/blog/2010/01/…
0

I used Northwind DB and :

ALTER TRIGGER Update_StockQuantity ON dbo.[Order Details] 
AFTER INSERT, UPDATE, DELETE 
AS 
BEGIN 
    declare @productId int
    declare @quantity smallint
    declare @quantityBefore smallint

    --Read Table Before Update
    SELECT ProductID, ProductName, UnitsInStock FROM Products WHERE ProductID = @productId

    -- UPDATE
    IF EXISTS (SELECT * FROM inserted) AND EXISTS (SELECT * FROM deleted)
    BEGIN
        SELECT @productId=ProductID, @quantity=Quantity FROM inserted
        SELECT @quantityBefore=Quantity FROM deleted

        UPDATE Products SET UnitsInStock = UnitsInStock - @quantity + @quantityBefore WHERE ProductID = @productId
    END

    -- INSERT
    IF EXISTS (SELECT * FROM inserted) AND NOT EXISTS(SELECT * FROM deleted)
    BEGIN
        SELECT @productId=ProductID, @quantity=Quantity FROM inserted

        UPDATE Products SET UnitsInStock = UnitsInStock - @quantity WHERE ProductID = @productId
    END

    -- DELETE
    IF EXISTS (SELECT * FROM deleted) AND NOT EXISTS(SELECT * FROM inserted)
    BEGIN
        SELECT @productId=ProductID, @quantity=Quantity FROM deleted

        UPDATE Products SET UnitsInStock = UnitsInStock + @quantity WHERE ProductID = @productId
    END

    --Read Table After Update
    SELECT ProductID, ProductName, UnitsInStock FROM Products WHERE ProductID = @productId

END

1 Comment

As it’s currently written, your answer is unclear. Please edit to add additional details that will help others understand how this addresses the question asked. You can find more information on how to write good answers in the help center.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.