Responding To Data Manipulation Via Triggers
Responding To Data Manipulation Via Triggers
Responding to Data
Manipulation via
Triggers
Module Overview
• Designing DML Triggers
• Implementing DML Triggers
• Advanced Trigger Concepts
Lesson 1: Designing DML Triggers
• What Are DML Triggers?
• AFTER Triggers vs. INSTEAD OF Triggers
• Inserted and Deleted Virtual Tables
• SET NOCOUNT ON
• Trigger Considerations
What Are DML Triggers?
• AFTER triggers
• Allow us to access the state of the data before and after the
modification began
• Virtual tables are often joined to the modified table data
• Available in both AFTER and INSTEAD OF triggers
CREATE
CREATE TRIGGER
TRIGGER TR_Opportunity_Insert
TR_Opportunity_Insert
ON
ON Sales.Opportunity
Sales.Opportunity
AFTER
AFTER INSERT
INSERT AS
AS
BEGIN
BEGIN
SET
SET NOCOUNT
NOCOUNT ON;
ON;
INSERT
INSERT INTO
INTO Sales.OpportunityAudit
Sales.OpportunityAudit
(OpportunityID,
(OpportunityID, ActionPerformed,
ActionPerformed, ActionOccurredAt)
ActionOccurredAt)
SELECT
SELECT i.OpportunityID,
i.OpportunityID,
'I',
'I',
SYSDATETIME()
SYSDATETIME()
FROM
FROM inserted
inserted AS
AS i;
i;
END;
END;
Demonstration 2A: Working with AFTER INSERT Triggers
CREATE TRIGGER
TRIGGER TR_Category_Delete
TR_Category_Delete
ON
ON Product.Category
Product.Category
AFTER
AFTER DELETE
DELETE AS
AS
BEGIN
BEGIN
SET
SET NOCOUNT
NOCOUNT ON;
ON;
UPDATE
UPDATE pp SET
SET p.Discontinued
p.Discontinued == 1
FROM
FROM Product.Product
Product.Product AS
AS p
WHERE
WHERE EXISTS
EXISTS (SELECT
(SELECT 1
1 FROM
FROM deleted
deleted AS
AS d
d
WHERE
WHERE p.CategoryID
p.CategoryID = d.CategoryID);
d.CategoryID);
END;
END;
GO
GO
Demonstration 2B: Working with AFTER DELETE
Triggers
CREATE
CREATE TRIGGER
TRIGGER TR_ProductReview_Update
TR_ProductReview_Update
ON
ON Product.ProductReview
Product.ProductReview
AFTER
AFTER UPDATE
UPDATE AS
AS
BEGIN
BEGIN
SET
SET NOCOUNT
NOCOUNT ON;
ON;
UPDATE
UPDATE pr
pr
SET
SET pr.ModifiedDate
pr.ModifiedDate == SYSDATETIME()
SYSDATETIME()
FROM
FROM Product.ProductReview
Product.ProductReview ASAS pr
pr
INNER
INNER JOIN
JOIN inserted
inserted AS
AS ii
ON
ON i.ProductReviewID
i.ProductReviewID == pr.ProductReviewID;
pr.ProductReviewID;
END;
END;
Demonstration 2C: Working with AFTER UPDATE
Triggers
CREATE
CREATE TRIGGER
TRIGGER TR_ProductReview_Delete
TR_ProductReview_Delete
ON
ON Product.ProductReview
Product.ProductReview
INSTEAD
INSTEAD OFOF DELETE
DELETE AS
AS
BEGIN
BEGIN
SET
SET NOCOUNT
NOCOUNT ON;
ON;
UPDATE
UPDATE pr
pr SET pr.Discontinued
pr.Discontinued =
= 11
FROM
FROM Product.ProductReview
Product.ProductReview AS
AS pr
pr
INNER
INNER JOIN
JOIN deleted
deleted as
as d
d
ON
ON pr.ProductReviewID
pr.ProductReviewID =
= d.ProductReviewID;
d.ProductReviewID;
END;
END;
Demonstration 3A: Working with INSTEAD OF Triggers
INSERT, UPDATE, or
1 DELETE statement
3…and so on…
2
Trigger executes
INSERT, UPDATE,
or DELETE on
another table…
Considerations for Recursive Triggers
ALTER
ALTER DATABASE
DATABASE MarketDev
MarketDev
SET
SET RECURSIVE_TRIGGERS
RECURSIVE_TRIGGERS ON
ON
Considerations:
• Careful design and thorough testing to ensure that the 32 level
nesting limit is not exceeded
• Can be difficult to control the order of table updates
• Can usually be replaced with non-recursive logic
• Option only affects direct recursion
UPDATE Function
• UPDATE determines if a particular column is being updated
• Used in triggers AFTER INSERT or AFTER UPDATE
CREATE
CREATE TRIGGER
TRIGGER TR_Product_Update_ListPriceAudit
TR_Product_Update_ListPriceAudit
ON
ON Production.Product
Production.Product
AFTER
AFTER UPDATE
UPDATE AS
AS
BEGIN
BEGIN
IF
IF UPDATE(ListPrice)
UPDATE(ListPrice)
BEGIN
BEGIN
INSERT
INSERT INTO
INTO Production.ListPriceAudit
Production.ListPriceAudit
(ProductID,
(ProductID, ListPrice,
ListPrice, ChangedWhen)
ChangedWhen)
SELECT
SELECT i.ProductID,
i.ProductID,
i.ListPrice,
i.ListPrice,
SYSDATETIME()
SYSDATETIME()
FROM
FROM inserted
inserted AS
AS i;
i;
END;
END;
END;
END;
Trigger Firing Order
EXEC
EXEC sp_settriggerorder
sp_settriggerorder
@triggername=
@triggername=
'Production.TR_Product_Update_ListPriceAudit',
'Production.TR_Product_Update_ListPriceAudit',
@order='First',
@order='First',
@stmttype
@stmttype =
= 'UPDATE';
'UPDATE';
Alternatives to Using Triggers
Logon information
• Best Practices