There are two primary mechanisms for enforcing business
rules and data integrity first is Constraints and second is Triggers.
Triggers are special type of stored procedure that
automatically initiates an action when DML or DDL event occurs in database.
Triggers are stored in Database; it is basically used to
maintain referential integrity of data. A trigger can’t be called and executed
like stored procedure, DBMS automatically fires the trigger when DML or DDL
event occurs in the database that is why we call Triggers as event driven stored
procedure.
Triggers are attached to a specific table, View or
database.
There are two types of Trigger in SQL Server.
1- DML Trigger
2- DDL Trigger
DML Triggers
DML Triggers are those triggers which are automatically
fired whenever any DML event takes place in the database. A DML event includes
INSERT, UPDATE, and DELETE. DML Trigger can be created on Table and Views.
A DML Trigger can query other tables and can include
complex TSQL commands. The Trigger and Statement that fires it are treated as a
single Transaction which can be rolled back from within the Trigger.
In SQL Server DML Triggers are disabled on Truncate Table
and Bulk Insert Operation.
DML Triggers are useful in these ways
·
They can cascade changes through related tables
in the database.
·
They can guard against wrong or malicious INSERT,
UPDATE and DELETE operations.
·
Unlike CHECK Constraints, DML Triggers can
reference columns in other tables.
·
They can evaluate the state of a table before
and after a data modification with the help of Inserted and Deleted temporary
table and take actions based on that difference.
·
Multiple DML Triggers of the same type (INSERT,
UPDATE, DELETE) on a table allow multiple, different actions to take place in
response to the same modification statement.
·
They can be used for auditing purpose.
There are basically two types of DML Trigger
1- AFTER Trigger.
2- INSTEAD OF Trigger.
AFTER Trigger
AFTER Triggers are also called as FOR Trigger. After
Triggers are fired after the DML event (INSERT, UPDATE, and DELETE). We can’t
create AFTER Trigger on Views. This Trigger can be created only on Tables.
INSTEAD OF
Trigger
As name suggest INSTEAD OF Triggers are fired in place of
DML Event (INSERT, UPDATE, and DELETE), therefore overriding the actions of the
triggering statements. INSTEAD OF Triggers can be created on both Table and
Views. At most one INSTEAD OF Trigger per INSERT ,UPDATE, DELETE statement can
be defined on a table or view. INSTEAD OF Triggers are not allowed on updatable
views that use WITH CHECK OPTION.
I have already explained how to create a INSTEAD OF
Trigger on Views. Click
here to know about Views in SQL Server and How INSTEAD OF Trigger works on
Views.
Syntax to
create DML Trigger
CREATE TRIGGER Trigger_Name
ON TABLE|VIEW (TABLE OR VIEW on which DML trigger will be created,
also referred as Trigger Table and Trigger View )
[WITH ENCRYPTION] (Encrypts
the text of the CREATE TRIGGER statement)
AFTER|INSTEAD OF (Decide
AFTER or INSTEAD OF as par the requirement)
INSERT | UPDATE | DELETE (Specifies the data modification statement that
activate the DML Trigger)
AS
BEGIN
TSQL Statement (Write your TSQL code that should be execute on DML event)
BEGIN
TSQL Statement (Write your TSQL code that should be execute on DML event)
END
Syntax to Drop DML
Trigger
DROP TRIGGER Trigger_Name
Syntax to
Modify DML Trigger
ALTER TRIGGER Trigger_Name
ON TABLE|VIEW (TABLE OR VIEW on which DML trigger will be created,
also referred as Trigger Table and Trigger View )
[WITH ENCRYPTION] (Encrypts
the text of the CREATE TRIGGER statement)
AFTER|INSTEAD OF (Decide
AFTER or INSTEAD OF as par the requirement)
INSERT | UPDATE | DELETE (Specifies the data modification statement that
activate the DML Trigger)
AS
BEGIN
TSQL Statement (Write your new TSQL code that should be execute on DML event)
BEGIN
TSQL Statement (Write your new TSQL code that should be execute on DML event)
END
Syntax to
Disable DML|DDL Trigger
DISABLE TRIGGER Trigger_Name|ALL| ON
TABLE|VIEW|DATABASE|ALL SERVER
(If you will use ALL then
it will disable all available triggers in a database.)
Inserted and
Deleted Tables in Trigger
Inserted and Deleted plays a very important role in
Triggers, it is also known as Magic Table. Both tables will be created in Temp DB
by the trigger. These two tables are only accessible in Trigger, in another way
we can say scope of these tables are until trigger is active. Once Trigger
executes SQL Server automatically drops these two tables. User can’t access
these two tables outside Triggers. User can’t perform any DML or DDL operation
on these two magic tables. These magic tables are read only tables. When we try
to perform any DML operation on table if table contains DML trigger then the
values of DML statement will be copied in these two magic tables. Structure of
these two tables will be same to our Trigger table. Trigger table means table which
has trigger. Inserted and deleted table can contain multiple records, it
depends on the transaction.
Let’s understand how these two tables work in DML
operation.
DELETE Operation
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 into DELETED
Magic table. Trigger Table and Magic table DELETED have no rows in common.
INSERT Operation
INSERTED table stores copies of the affected rows during
INSERT and UPDATE statements. During the execution of an INSERT or UPDATE
statement, new rows are added at the same time to Trigger Table and INSERTED Magic
table. The rows in INSERTED table are copies of the new rows in the Trigger
table.
UPDATE Operation
An UPDATE transaction is similar to DELETE operation followed
by an INSERT operation. The old records are copied to the DELETED Magic table
first, and then the new rows are copied to the Trigger Table and to INSERTED Magic
table.
DML Trigger
example
Task - A Trigger that will convert the Dname and Loc into
Upper case when the user insert in lower case.
1- AFTER Trigger
/*CREATING A NEW
DATABASE*/
USE MASTER
IF EXISTS(SELECT NAME FROM SYS.DATABASES WHERE NAME='TEACHMESQLSERVER')
DROP DATABASE TEACHMESQLSERVER
GO
CREATE DATABASE TEACHMESQLSERVER
/*CREATING NEW
DEP TABLE AND POPLUTAING DATA*/
GO
USE
TEACHMESQLSERVER
GO
CREATE TABLE DEP (DEPID INT PRIMARY KEY IDENTITY (1,1), DNAME VARCHAR(MAX), LOC VARCHAR(MAX))
GO
INSERT INTO DEP VALUES ('GHANESH','INDIA'),('KEVIN','USA'),('anvie','uk')
GO
SELECT * FROM DEP /*YOU CAN SEE RESULT SHOWS FIRST TWO ROWS ARE ALL IN UPPER
CASE AND THIRD ROW IS IN LOWER CASE*/
GO
/*CREATING AFTER
DML TRIGGER ON DEP TABLE TO CONVERT LOWER CASE TO UPPER CASE, THIS TRIGGER WILL
WORK ONLY FOR SINGLE RECORD GETTING INSERTED INTO TABLE*/
CREATE TRIGGER DEPTRIGGER
ON DEP
WITH ENCRYPTION
AFTER INSERT
AS
BEGIN
DECLARE @DEPID INT,@DEPNAME VARCHAR(MAX), @LOCATION VARCHAR(MAX)
SELECT @DEPID=DEPID, @DEPNAME=DNAME , @LOCATION=LOC FROM INSERTED
UPDATE DEP SET DNAME=UPPER(@DEPNAME),LOC=UPPER(@LOCATION) WHERE DEPID=@DEPID
END
GO
/*INSERTING NEW
RECORD IN LOWER CASE*/
INSERT INTO DEP VALUES ('gautam','japan')
GO
SELECT * FROM DEP /*YOU CAN SEE FOURTH RECORD WAS ENTERED IN LOWER CASE BUT
IT WAS CONVERTED INTO UPPER CASE IN TRIGGER TABLE*/
GO
We can accomplish the same thing using INSTEAD OF Trigger,
Below is the example.
2- INSTEAD OF Trigger
*DROPPING AFTER
DML TRIGGER FROM DEP TABLE*/
GO
DROP TRIGGER DEPTRIGGER
GO
/*CREATING INSTEAD
OF DML TRIGGER ON DEP TABLE TO CONVERT LOWER CASE TO UPPER CASE, THIS TRIGGER
WILL WORK ONLY FOR SINGLE RECORD GETTING INSERTED INTO TABLE*/
CREATE TRIGGER DEPTRIGGER
ON DEP
WITH ENCRYPTION
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO DEP SELECT UPPER(DNAME) , UPPER(LOC) FROM INSERTED
END
GO
/*INSERTING NEW
RECORD IN LOWER CASE*/
INSERT INTO DEP VALUES ('Prasad','china')
GO
SELECT * FROM DEP /*YOU CAN SEE FIFTH RECORD WAS ENTERED IN LOWER CASE BUT IT
WAS CONVERTED INTO UPPER CASE IN TRIGGER TABLE*/
GO
Once you create a trigger it gets stored in database. You
can easily find it. There are many ways to find Trigger in a database.
Method 1-
Go to in Object
Explorer ----> Tables ----> Your Table (i.e DEP Table) ---->Triggers
under Trigger you will find Trigger if present, in our case we recently created DEPTRIGGER.
Method 2-
You can find all Triggers present in your database using
System Views. Click here to know about System Views.
Run any of the below query to get list of all Triggers in
your database.
GO
SELECT * FROM SYS.triggers
GO
SELECT * FROM SYS.objects WHERE TYPE='TR'
In our case we have only one trigger in our database that
is why only DEPTRIGGER is returned, If you want to find on which object your trigger
was created then use Parent_Id from above queries and pass it into below query.
GO
SELECT * FROM SYS.objects WHERE OBJECT_ID=581577110
You can see query shows we had created DEPTRIGGER
on DEP Table.
Disable-Enable Trigger
Suppose you don’t want Trigger to fire on any DML or DDL event, There are two ways to achieve this one is drop the Trigger and if you don’t want to drop your Trigger then Disable the trigger.
Let’s Disable DEPTRIGGER
GO
DISABLE TRIGGER
DEPTRIGGER ON DEP
You have successfully disabled the Trigger , now if you
will execute any DML command it will execute on DML Event let’s try.
GO
INSERT INTO DEP VALUES ('kumar','india')
GO
SELECT * FROM DEP
As you can see Dname and Loc was not changed to UPPER
CASE.
We can enable Trigger using Enable keywor, Below you can see the code.
GO
GO
ENABLE TRIGGER DEPTRIGGER ON DEP
Change Trigger Execution Sequence
We can have many DML triggers on a single Table or View
for the same event.
Generally execution sequence will follow Queue Data
structure (first come first serve) concept. I will try to explain this suppose we
have four Triggers Trigger1, Trigger2, Trigger3 and Trigger4 on
DEP Table. First we created Trigger1
then Trigger2 then Trigger3 and last Trigger4 on DEP Table. When any DML event occurs on DEP Table, Trigger1 will be executed first. Once Trigger1 completes; Trigger2 will get the control and it
will get executed then Trigger3 and
last Trigger4 will get executed. Trigger2 will get control only after completion
of First Trigger Trigger1. If Trigger1 fails with any error in that
case also Trigger2, Trigger3 and Trigger4 will be fired.
Let’s create these four Triggers on DEP Table.
/*CREATING FOUR
TRIGGERS ON DEP TABLE ON INSERT DML OPERATION*/
CREATE TRIGGER TRIGGER1 ON
DEP
AFTER INSERT
AS
BEGIN
PRINT 'THIS CODE IS PRINTED BY TRIGGER1'
END
GO
CREATE TRIGGER TRIGGER2 ON
DEP
AFTER INSERT
AS
BEGIN
PRINT 'THIS CODE IS PRINTED BY TRIGGER2'
END
GO
CREATE TRIGGER TRIGGER3 ON
DEP
AFTER INSERT
AS
BEGIN
PRINT 'THIS CODE IS PRINTED BY TRIGGER3'
END
GO
CREATE TRIGGER TRIGGER4 ON
DEP
AFTER INSERT
AS
BEGIN
PRINT 'THIS CODE IS PRINTED BY TRIGGER4'
END
GO
Now let’s create an INSERT DML Event and will see the execution
sequence of all four Triggers.
GO
SET NOCOUNT ON
INSERT INTO
DEP VALUES ('Anshul','India')
Once we execute above query our four triggers
gets fired one after another. From the result you can easily find the execution
sequence of all four Triggers. Trigger1 was executed first and Trigger4 was
executed last. Execution sequence and Triggers creation sequence are same.
If you want to change execution sequence of trigger then you
can change Trigger execution sequence by using SP_Settriggerorder system stored procedure. SP_Settriggerorder Specifies which AFTER trigger will be fired
first or last. The AFTER triggers that are fired between the first and last
triggers are executed in undefined order.
Let’s change the Execution sequence order of Trigger. I
want my Trigger3 should be fired
first and Trigger1 should be fired
last.
Sp_SETTRIGGERORDER Stored procedure has four string parameters.Click here to know more about SP_SETTRIGGERORDER stored procedure.
@triggername= ‘trigger name’
@order= ’value’
@stmttype= ’statement type'
@namespace = 'DATABASE' | 'SERVER' |
NULL (Database or Server for DDL Triggers, NULL
for DML Triggers)
GO
EXEC sp_settriggerorder 'TRIGGER3','FIRST','INSERT' /*ASSISNING
ORDERVALUE FOR FIRST*/
GO
EXEC sp_settriggerorder 'TRIGGER1','LAST','INSERT' /*ASSISNING ORDERVALUE FOR LAST*/
GO
INSERT INTO
DEP VALUES ('YOGITA','India')
Delete all
Triggers
If you want to drop all triggers from your database then
you can use below code.
USE
TEACHMESQLSERVER
GO
/*LETS DROP ALL
TRIGGERS FROM OUR DATABASE */
DECLARE @SQL VARCHAR(MAX),@TRIGGERNAME VARCHAR(MAX)
SET @SQL ='DROP TRIGGER '
SET
@TRIGGERNAME=(SELECT
TOP 1 NAME FROM
SYS.TRIGGERS)
SELECT
@TRIGGERNAME= @TRIGGERNAME+','+NAME FROM SYS.triggers WHERE name <>@TRIGGERNAME
SET @SQL= @SQL+@TRIGGERNAME
EXEC(@SQL)
PRINT 'Trriger '+'('+@TRIGGERNAME+')' +' Has been Dropped'
GO
As you can see it has deleted all four Triggers we had
created in our previous exercise.
Nested Triggers
If a trigger changes a table on which there is another
Trigger, the second Trigger is activated and can then call a third trigger and
so on. Triggers can be nested to a maximum of 32 levels. We can disable nested
triggers, using system stored procedure sp_configure
to 0, by default SQL Server allows for nested triggers.
I will explain how Nested Triggers works with a simple
example.
I will use my previous created table DEP, I will also
create a new DuplicateDep table. This table will be a duplicate table of DEP
table, whenever any new record will be entered into this table, it will be
copied to this DuplicateDep table.
This example is demonstrated to understand the concept of
nested triggers, it’s a basic code you can make more interactive code.
GO
SELECT * FROM DEP
GO
SELECT * INTO DUPLICATEDEP FROM DEP /*CREATING A NEW
TABLE FROM DEP TABLE AND POPULATING DATA INTO IT*/
GO
SELECT * FROM DUPLICATEDEP
GO
CREATE TRIGGER DEPTRIGGER ON
DEP /*CREATING DML TRIGGER ON DEP TABLE, IT WILL MAKE
CHANGE IN DUPLICATEDEP TABLE*/
AFTER INSERT
AS
INSERT INTO DUPLICATEDEP SELECT
DNAME,LOC FROM
INSERTED
PRINT 'A NEW RECORD HAS BEEN ADDED INTO DUPLICATEDEP TABLE'
GO
CREATE TRIGGER DUPLICATEDEPTRIGGER ON
DUPLICATEDEP /*CREATING DUPLICATEDEPTRIGGER ON
DUPLICATEDEP TABLE, THIS TRIIGGER WILL BE FIRED IF INSERT DML EVENT OCCURS*/
AFTER INSERT
AS
PRINT 'New Record was inserted by DEPTRIGGER'+char(10)
GO
SET NOCOUNT ON
INSERT INTO DEP VALUES('SAURABH','USA')
New record was
successfully inserted into DUPLICATEDEP Table, This record was inserted by
DEPTRIGGER, AS you know we also have more Trigger on DuplicateDep Table which
will fire whenever any INSERT command will be executed on DuplicateDep table.
In this case INSERT command was executed by DEPTRIGGER. In my definition “If a
trigger changes a table on which there is another Trigger, the second Trigger
is activated” this is known as Nested Trigger.
You can check that new
record is also available in DUPLICATEDEP Table.
GO
SELECT * FROM DUPLICATEDEP
DML Triggers
Important points
·
We can execute Stored Procedure in Trigger’s SQL
Statement
·
We can use CTE in Trigger’s SQL Statement
·
We can perform DML and DDL operations in
Trigger’s
·
We can call functions in Triggers
·
We can use Temporary Tables in Triggers
·
Inserted and delete magic tables follow stack
data structure concept for data insertion, deletion.
·
We can use Cursors in Triggers
·
Trigger will be fired per Transaction.
DDL Triggers
DDL Triggers are those triggers which are automatically
fired whenever any DDL event takes place in the Database or Server. There are
many DDL events some of them are CREATE, DROP, ALTER. DDL Triggers are only
AFTER Triggers which can be created on Database or Servers. We can’t create DDL
Trigger on Tables or Views. DDL Triggers can be created either Database or
Server. Syntax to create DDL Trigger is similar to DML Trigger. You can use DDL
and DML command in DDL Trigger SQL Statement block.
If you have Server Scope Trigger and Database scope
Trigger then Server Scope Trigger always Fire First.
Let’s create one DDL Trigger to understand how it works
Suppose you don’t want any user to CREATE, DROP or ALTER
Table in your database in that case you can create a DDL Trigger on your
database.
USE
TEACHMESQLSERVER
GO
CREATE TRIGGER FIRSTDDL ON DATABASE
AFTER
CREATE_TABLE,DROP_TABLE,
ALTER_TABLE /*THESE ARE DDL EVENTS*/
AS
ROLLBACK
PRINT 'YOU CANT CREATE/DROP/MODIFY TABLE IN THIS DATABASE.'
GO
You have successfully
creatd DDL Trigger on TEACHMESQLSERVER Database, similar to this you can Create DDL Trigger on Servers.
Now If you will run CREATE, DROP and ALTER command it will not allow. Let’s try to run CREATE, DROP and ALTER command.
Now If you will run CREATE, DROP and ALTER command it will not allow. Let’s try to run CREATE, DROP and ALTER command.
GO
CREATE TABLE EMP1 (EMPID INT ,EMPNAME VARCHAR(MAX))
GO
DROP TABLE DEP
GO
ALTER TABLE DEP ADD
FULLNAME VARCHAR(MAX)
We couldn’t perform any
of the operation we got an error message. This is the beauty of DDL Trigger
There are many DDL Event, All DDL Trigger Events are stored in SQL Server Database. You can easily find them using System View. The below query will give you list of all available DDL Events.
Like DML Trriggers all DDL
Database Triggers will be stored in the datbase, beasue these triggers will be
created on Database or Server so finding them in database is different from
fiding DML Triggers.
You can find DDL Database
Triggers under the follwing path.
Or you can query against system table SELECT * FROM SYS.TRIGGERS
DDL Server Scope Trigger can be find under SYS.SERVER_TRIGGERS system
table, you can query against system table SELECT * FROM SYS.SERVER_TRIGGERS
There are many DDL Event, All DDL Trigger Events are stored in SQL Server Database. You can easily find them using System View. The below query will give you list of all available DDL Events.
SELECT * FROM SYS.TRIGGER_EVENT_TYPES
Syntax to Drop DDL
Trigger
DROP TRIGGER Trigger_Name on Database| All Server
I hope you enjoyed the article don't forget to share on facebook. Please leave your comments if
there are any questions.
No comments:
Post a Comment