Documentation

SQL Triggers

This section provides detailed information about SQL Server triggers, including their purpose, types, syntax, and best practices.

What is a SQL Trigger?

A trigger is a special type of stored procedure that automatically executes or is fired when an event occurs in the database. These events are typically data modification language (DML) statements such as INSERT, UPDATE, or DELETE on a specific table. Triggers can also be fired by data definition language (DDL) statements or database-level events.

Tip: Triggers are often used to enforce complex business rules, maintain data integrity, audit data changes, or automate data synchronization.

Types of Triggers

SQL Server supports several types of triggers:

DML Triggers

DML triggers are the most common type. They can be further categorized:

Creating an AFTER Trigger

The basic syntax for creating an AFTER trigger is:

CREATE TRIGGER trigger_name
ON table_name
AFTER INSERT, UPDATE, DELETE
AS
BEGIN
    -- Trigger logic goes here
    -- Use the inserted and deleted pseudo-tables
END;

Inside a DML trigger, you can access two special tables:

Example: Audit Trigger

This trigger logs changes to the Products table into an audit table.

CREATE TRIGGER trg_ProductAudit
ON Products
AFTER UPDATE, DELETE
AS
BEGIN
    SET NOCOUNT ON;

    IF EXISTS (SELECT * FROM inserted) AND EXISTS (SELECT * FROM deleted)
    BEGIN -- UPDATE operation
        INSERT INTO ProductAuditLog (ProductID, OldPrice, NewPrice, ChangeDate, ChangeType)
        SELECT
            d.ProductID,
            d.Price,
            i.Price,
            GETDATE(),
            'UPDATE'
        FROM deleted d
        JOIN inserted i ON d.ProductID = i.ProductID;
    END
    ELSE IF EXISTS (SELECT * FROM deleted)
    BEGIN -- DELETE operation
        INSERT INTO ProductAuditLog (ProductID, OldPrice, NewPrice, ChangeDate, ChangeType)
        SELECT
            d.ProductID,
            d.Price,
            NULL,
            GETDATE(),
            'DELETE'
        FROM deleted d;
    END
END;
Note: Always use SET NOCOUNT ON; at the beginning of your trigger to prevent sending the count of affected rows back to the client, which can sometimes interfere with application logic or cause performance overhead.

Creating an INSTEAD OF Trigger

The syntax for an INSTEAD OF trigger is similar:

CREATE TRIGGER trigger_name
ON table_or_view_name
INSTEAD OF INSERT, UPDATE, DELETE
AS
BEGIN
    -- Trigger logic to perform the action instead of the original DML statement
END;

Example: INSTEAD OF Trigger for a View

Consider a view that combines data from multiple tables. An INSTEAD OF trigger can handle INSERT operations on this view.

-- Assuming View 'vw_CustomerOrderDetails' combines Customer and Order info
CREATE TRIGGER trg_vw_CustomerOrderDetails_Insert
ON vw_CustomerOrderDetails
INSTEAD OF INSERT
AS
BEGIN
    SET NOCOUNT ON;

    -- Insert into Customers table if customer doesn't exist
    INSERT INTO Customers (CustomerID, FirstName, LastName)
    SELECT i.CustomerID, i.FirstName, i.LastName
    FROM inserted i
    LEFT JOIN Customers c ON i.CustomerID = c.CustomerID
    WHERE c.CustomerID IS NULL;

    -- Insert into Orders table
    INSERT INTO Orders (OrderID, CustomerID, OrderDate)
    SELECT i.OrderID, i.CustomerID, GETDATE()
    FROM inserted i;
END;

DML Trigger Considerations

DDL Triggers

DDL triggers respond to events like CREATE TABLE, ALTER VIEW, DROP DATABASE, etc. They are useful for auditing DDL changes or enforcing DDL policies.

CREATE TRIGGER trg_DDL_PreventDropTable
ON DATABASE
AFTER DROP_TABLE
AS
BEGIN
    PRINT 'Dropping tables is not allowed by this trigger.';
    ROLLBACK; -- Revert the DROP TABLE operation
END;

Best Practices