Triggers in SQL Server

The trigger is a database object similar to a stored procedure that is executed automatically when an event occurs in a database. There are different kinds of events that can activate a trigger like inserting or deleting rows in a table, a user logging into a database server instance, an update to a table column, a table is created, altered, or dropped, etc.

For example, consider a scenario where the salary of an employee in the Employee table is updated. You might want to preserve the previous salary details in a separate audit table before it gets updated to its new value. You can create a trigger to automatically insert updated employee data to the new audit table whenever the Employee table's value is updated.

There are three types of triggers in SQL Server

  • DML triggers are automatically fired when an INSERT, UPDATE or DELETE event occurs on a table.
  • DDL triggers are automatically invoked when a CREATE, ALTER, or DROP event occurs in a database. It is fired in response to a server scoped or database scoped event.
  • Logon trigger is invoked when a LOGON event is raised when a user session is established.

DML Triggers

DML (Data Manipulation Language) trigger is automatically invoked when an INSERT, UPDATE or DELETE statement is executed on a table.

Use the CREATE TRIGGER statement to create a trigger in SQL Server.

Syntax: Create Trigger
CREATE TRIGGER [schema_name.]trigger_name
ON { table_name | view_name }
{ FOR | AFTER | INSTEAD OF } {[INSERT],[UPDATE],[DELETE]}
[NOT FOR REPLICATION]
AS
    {sql_statements}

In the above syntax:

  • schema_name (optional) is the name of the schema where the new trigger will be created.
  • trigger_name is the name of the new trigger.
  • ON { table_name | view_name } keyword specifies the table or view name on which the trigger will be created.
  • AFTER clause specifies the INSERT, UPDATE or DELETE event which will fire the trigger. The AFTER clause specifies that the trigger fires only after SQL Server successfully completes the execution of the action that fired it. All other actions and constraints should be successfully executed before the trigger is fired.
  • INSTEAD OF clause is used to skip an INSERT, UPDATE or DELETE statement to a table and instead, executes other statements defined in the trigger. So, the actual INSERT, UPDATE or DELETE statement does not happen at all. INSTEAD OF clause cannot be used on DDL triggers.
  • [NOT FOR REPLICATION] clause is specified to instruct the SQL Server not to invoke the trigger when a replication agent modifies the table.
  • sql_statements specifies the action to be executed when an event occurs.

DML triggers use two special temporary tables called inserted tables and deleted tables. SQL Server automatically creates and manages these tables. SQL Server uses these tables to find the state of a table before and after a data modification and take action based on that difference.

INSERTED Table DELETED Table
Holds the new rows to be inserted during an INSERT or UPDATE event. Holds copies of the affected rows during a DELETE or UPDATE event.
No records for the DELETE statements. No records for the INSERT statements.

Let's create a trigger that fires on INSERT, UPDATE and DELETE operation on the Employee table. For that, create a new table EmployeeLog to log all operation performed on the Employee table.

Example: Create Log Table
CREATE TABLE EmpLog (
	LogID int IDENTITY(1,1) NOT NULL,
	EmpID int NOT NULL,
	Operation nvarchar(10) NOT NULL,
	UpdatedDate Datetime NOT NULL	
)

In the above table, LogID is the serial number with auto increment, UpdatedDate is the date on which the Employee table was updated. The Operation column stores the type of operation made to the table; either "INSERT", "UPDATE", or "DELETE".

FOR Triggers

The FOR triggers can be defined on tables or views. It fires only when all operations specified in the triggering SQL statement have initiated successfully. All referential cascade actions and constraint checks must also succeed before this trigger fires.

The following FOR trigger fires on the INSERT operation on the Employee table.

Example: FOR Trigger
CREATE TRIGGER dbo.trgEmployeeInsert
ON dbo.Employee
FOR INSERT	
AS
    INSERT INTO dbo.EmpLog(EmpID, Operation, UpdatedDate)
    SELECT EmployeeID ,'INSERT',GETDATE() FROM INSERTED; --virtual table INSERTED

The above will create the trgEmployeeInsert trigger in the <table_name> -> Triggers folder, as shown below.

Triggers in SQL Server

Execute the select statements on Employee and EmpLog tables to see the existing records.

The following is EmpLog table.

Now, execute the following INSERT statement that will fire the trgEmployeeInsert trigger.

Example: INSERT Data
INSERT INTO Employee(FirstName
           ,LastName
           ,EMail
           ,Phone
           ,HireDate
           ,ManagerID
           ,Salary
           ,DepartmentID)
     VALUES('Manisha'
           ,'Dutt'
           ,'[email protected]'
           ,6799878453
           ,'11/07/2015'
           ,5
           ,50000
           ,20)

The above will insert a new row in the Employee table, as shown below.

The trgEmployeeInsert will be fired and insert a row in the EmpLog table, as shown below.

You can see that a new row is inserted in the EmpLog table for each INSERT statement for the Employee table.

Note: For any reason, if the FOR triggers fails then the INSERT will also fail and no rows will be inserted.

AFTER Triggers

The AFTER trigger fires only after the specified triggering SQL statement completed successfully. AFTER triggers cannot be defined on views.

For example, the following trigger will be fired after each UPDATE statement on the Employee table.

Example: AFTER Trigger
CREATE TRIGGER dbo.trgEmployeeUpdate
ON dbo.Employee
AFTER UPDATE
AS
    INSERT INTO dbo.EmpLog(EmpID, Operation, UpdatedDate)
    SELECT EmployeeID,'UPDATE', GETDATE() FROM DELETED;

To test this trigger, execute the following UPDATE statement.

Example: INSERT Data
UPDATE Employee
SET salary = 55000
WHERE EmployeeID = 2;

Now, select rows from the EmpLog table. The trgEmployeeUpdate trigger should have inserted a new row in the EmpLog table, as shown below.

INSTEAD OF Triggers

An INSTEAD OF trigger allows you to override the INSERT, UPDATE, or DELETE operations on a table or view. The actual DML operations do not occur at all.

The INSTEAD OF DELETE trigger executes instead of the actual delete event on a table or view. In the Instead Of delete trigger example below, when a delete command is issued on the Employee table, a new row is created in the EmpLog table storing the operation as 'Delete', but the row doesn't get deleted.

Example: INSTEAD OF Trigger
CREATE TRIGGER dbo.trgInsteadOfDelete 
ON dbo.Employee
INSTEAD OF DELETE
AS
    INSERT INTO dbo.EmpLog(EmpID, Operation, UpdatedDate)
    SELECT EmployeeID,'DELETE', GETDATE() FROM DELETED;

Now, execute the following delete statement to test the above trigger.

Example: INSTEAD OF Trigger
DELETE FROM Employee
WHERE EmployeeID = 16;

The above statement will fire the trgInsteadOfDelete trigger which will insert a new row in the EmpLog table instead of deleting a row in the Employee table.

The INSTEAD OF DELETE trigger works in the same manner for bulk deletes also. When you run an SQL statement deleting multiple rows, the rows will not be deleted, but equal number of rows gets inserted in the EmpLog table.

Multiple Triggers

In SQL Server, multiple triggers can be created on a table for the same event. There is no defined order of execution for these triggers.

The order of the triggers can be set to First or Last using the stored procedure sp_settriggerorder. There can be only one first or last trigger for a table. All triggers that are fired between the first defined trigger and the last defined trigger are not fired in any guaranteed order. Consider a scenario where there are four or more triggers. After the first defined trigger is fired, there is no defined order of firing for the other triggers until finally, the Last defined trigger is fired.

Syntax
sp_settriggerorder [ @triggername = ] 'triggername',
[ @order = ] 'value',  
[ @stmttype = ] 'statement_type',  
[ @namespace = { 'DATABASE' | 'SERVER' | NULL } ]

Arguments:

  • Triggername is the name of the trigger to be ordered
  • @order = Order of the trigger. First, Last or None
  • @stmttype = Statement type. INSERT UPDATE, DELETE, LOGON or any TSQL statement event listed in DDL events.
  • @namespace specifies whether the DDL trigger was created on Database or Server.

Assume that you have multiple triggers that fire on the update statement on the Employee table. The following example specifies that trigger trgEmployeeUpdate be the first trigger to fire after an UPDATE operation occurs on the Employee table.

Example: Set Trigger Order
sp_settriggerorder @triggername= 'dbo.trgEmployeeUpdate', 
    @order='First', 
    @stmttype = 'UPDATE';

Create a DML Trigger using SSMS

Step 1: Open SSMS and log in to the database server. In Object Explorer, expand the database instance and select the database where you want to create a trigger.

Step 2: Expand the table where you want to create a trigger. Right-click on the Triggers folder and select New Trigger. The CREATE TRIGGER syntax for a new trigger will open in Query Editor.

Step 3: In the Query menu, click Specify Values for Template Parameters.

In the dialog box, specify the trigger name, date created, schema name, author of the trigger, and fill the other parameters. Click Ok.

Step 4: In the Query Editor, enter the SQL statements for the trigger in the commented section – insert statements for trigger here.

Step 5: You can verify the syntax by clicking on Parse under the Query menu.

Step 6: Click Execute to create the trigger.

Step 7: Refresh the table. The new trigger will be created under the Triggers folder of the table.

Thus, you can create triggers in SSMS.