After Trigger, Instead of Trigger Example

Estimated study time: 30 minutes. See both trigger types act on the same INSERT.

The clearest way to understand AFTER and INSTEAD OF triggers is to watch them handle the exact same action differently. Below, both triggers respond to an INSERT into an Orders table.

Setting Up the Table

CREATE TABLE Orders (
    OrderId INT IDENTITY(1,1) PRIMARY KEY,
    ProductName VARCHAR(100),
    Quantity INT,
    OrderDate DATETIME DEFAULT GETDATE()
);

Example 1: AFTER INSERT Trigger

An AFTER trigger lets the insert happen first, then runs extra logic - here, logging the new order into an audit table.

CREATE TABLE OrderAudit (
    AuditId INT IDENTITY(1,1) PRIMARY KEY,
    OrderId INT,
    LoggedAt DATETIME DEFAULT GETDATE()
);
GO

CREATE TRIGGER trg_AfterOrderInsert
ON Orders
AFTER INSERT
AS
BEGIN
    INSERT INTO OrderAudit(OrderId)
    SELECT OrderId FROM inserted;
END;
GO

INSERT INTO Orders(ProductName, Quantity) VALUES ('Keyboard', 2);
-- Row is inserted into Orders AND a matching row appears in OrderAudit

Example 2: INSTEAD OF INSERT Trigger

An INSTEAD OF trigger takes over completely - the original INSERT never touches the table unless the trigger explicitly performs it. This is useful for validation before a row is allowed in.

CREATE TRIGGER trg_InsteadOfOrderInsert
ON Orders
INSTEAD OF INSERT
AS
BEGIN
    IF EXISTS (SELECT 1 FROM inserted WHERE Quantity <= 0)
    BEGIN
        PRINT 'Quantity must be greater than zero. Insert blocked.';
        RETURN;
    END

    INSERT INTO Orders(ProductName, Quantity, OrderDate)
    SELECT ProductName, Quantity, GETDATE() FROM inserted;
END;
GO

INSERT INTO Orders(ProductName, Quantity) VALUES ('Monitor', 0);
-- Blocked: Quantity must be greater than zero. Insert blocked.

INSERT INTO Orders(ProductName, Quantity) VALUES ('Monitor', 1);
-- Succeeds: row is inserted through the trigger's own INSERT statement

Key Difference

In the AFTER example, the row lands in Orders automatically, and the trigger only adds a side effect afterward. In the INSTEAD OF example, nothing reaches Orders unless the trigger's own logic writes it there - which is exactly what lets it reject bad data before it's ever stored.

💡 Tip: A table can have multiple AFTER triggers for the same event, but only one INSTEAD OF trigger per event, since it fully replaces the default behavior.

Ready to go beyond the basics?

Get hands-on training, live mentorship, and placement support with Uncodemy's Data Analytics Course.

Explore Data Analytics Course →