2. Using AFTER Triggers
An AFTER trigger is the original mechanism
that SQL Server created to provide an automated response to data
modifications. Prior to the release of SQL Server 2000, the AFTER trigger was the only type of trigger, and the word AFTER
was rarely used in its name. Any trigger written for prior versions of
SQL Server or documentation referring to these triggers is for AFTER triggers.
SQL Server 2000 introduced a new type of trigger called an INSTEAD OF trigger. This trigger is discussed later in the section titled “INSTEAD OF Triggers.” The introduction of that new trigger and inclusion of the word AFTER in the name of the old trigger have helped accentuate the behavior of the AFTER trigger: the AFTER trigger executes after a data modification has taken place.
The fact that an AFTER trigger fires after a data modification might seem to be a simple concept, but it is critical to understanding how it works. The AFTER
trigger fires after the data modification statement completes but
before the statement’s work is committed to the databases. The
statement’s work is captured in the transaction log but not committed to
the database until the trigger has executed and performed its actions.
The trigger has the capability to roll back its
actions as well as the actions of the modification statement that
invoked it. This is possible because an implicit transaction exists that
includes both the modification statement and trigger it fires. If the
trigger does not issue a rollback, an implicit COMMIT of all the work is issued when the trigger completes.
The basic syntax for creating an AFTER trigger is as follows:
CREATE TRIGGER trigger_name
ON table_name
AFTER { INSERT | UPDATE | DELETE }
AS
SQL statements
The AFTER trigger is the default type of DML trigger, so the AFTER keyword is optional.
Listing 1 shows the code you use to create a trigger in the BigPubs2008 database.This new trigger prints a message, stating the number of rows updated by
an UPDATE statement. You then execute a couple of UPDATE statements to see whether the trigger works.
Listing 1. An Example of a Simple AFTER Trigger
CREATE TRIGGER tr_au_upd ON authors
AFTER UPDATE
AS
PRINT 'TRIGGER OUTPUT: ' +CONVERT(VARCHAR(5), @@ROWCOUNT)
+ ' rows were updated.'
GO
UPDATE authors
SET au_fname = au_fname
WHERE state = 'UT'
GO
--TRIGGER OUTPUT: 1 rows were updated.
UPDATE authors
SET au_fname = au_fname
WHERE state = 'CA'
GO
--TRIGGER OUTPUT: 37 rows were updated.
|
Even though you do not actually change the contents of the au_fname column (because you set it to itself), the trigger fires anyway. Listing 30.1
does not show the typical use of a trigger, but it gives you some
insight into how and when a trigger fires. The fact that the trigger
fires, regardless of what is updated, causes many developers to test the
@@rowcount value at the beginning of the trigger code. If @@rowcount
is equal to zero, the trigger can return without executing the
remainder of the trigger code. This is a good tactic for optimizing the
performance of triggers.
Note
Triggers are meant to guarantee the integrity of
data. Although you can return result sets and messages in triggers,
doing so is not recommended. The programmers who write applications that
perform modifications on a table are probably not prepared to get
unexpected result sets or messages when they submit data modification
statements.
The exception is returning an error with the RAISERROR command. If a trigger performs ROLLBACK TRAN, it should also execute RAISERROR to communicate the failure to the application.
Executing AFTER Triggers
You know that the AFTER trigger fires when a
data modification (such as an insertion, an update, or a deletion)
takes place. What about the trigger’s execution in relationship to other
events, including the execution of constraints? The following events
take place before an AFTER trigger executes:
Constraint processing— This includes CHECK constraints, UNIQUE constraints, and PRIMARY KEY constraints.
Declarative referential actions— These actions are defined by FOREIGN KEY constraints that ensure the proper relationships between tables. This includes cascading FOREIGN KEY constraints.
Triggering action—
This data modification caused the trigger to fire. The action occurs
before the trigger fires, but the results are not committed to the
database until the trigger completes.
You need to consider this execution carefully when
you design triggers. For example, if you have a constraint and trigger
defined on the same column, any violations to the constraint
abort the statement, and the trigger execution does not occur. For
example, if you have a foreign key constraint on a table that ensures
referencial integrity and a trigger that that does some validation on
that same foreign key column then the trigger validation will only
execute if the foreign key validation is successful.
Specifying Trigger Firing Order
You can create more than one trigger on a table for
each data modification action. In other words, you can have multiple
triggers responding to an INSERT, an UPDATE, or a DELETE
command. This can be useful in certain situations, but it can generate
confusion because you might not know the order in which the triggers
fire for the particular action.
Some of the confusion has been alleviated by the fact
that SQL Server 2008 allows you to specify the first and last trigger
that fire for a particular action. If you have four triggers responding
to updates on a given table, you can set the order for two of the
triggers (first and last), but the order of the remaining two triggers
remains unknown.
The sp_settriggerorder procedure is the tool you use to set the trigger order. This procedure takes the trigger name, order value (FIRST, LAST, or NONE), and action (INSERT, UPDATE, or DELETE)
as parameters.
sp_settriggerorder tr_au_upd, FIRST, 'UPDATE'
The execution of this command sets the tr_au_upd trigger as the first trigger to fire when an update happens to the table on which this trigger has been placed. If an ALTER statement is executed against the trigger after the trigger order has been defined, the firing order is lost. The sp_settriggerorder procedure must be run again to reestablish the firing order.
Note
It is recommended that you avoid defining multiple
triggers for the same event on the same table when possible. Often, it
is possible to include all the logic in one trigger defined for an
action. This can simplify your database and avoid the uncertainty of the
firing order.
Special Considerations with AFTER Triggers
Following are a few other considerations for AFTER triggers:
AFTER triggers can be used on tables
that also have cascading referential integrity constraints. The
cascading feature, which was new to SQL Server 2000, allows you to
define cascading actions when a user updates or deletes a primary key to
which a foreign key points.
WRITETEXT and TRUNCATE TABLE do not fire triggers. BCP, by default, does not fire triggers either, but the FIRE_TRIGGERS bulk copy hint can be specified to cause both AFTER and INSTEAD OF triggers to execute.
Triggers
are objects, so they must have unique names within the database. If you
try to add a trigger with a name that already exists, you get an error
message. You can, however, use ALTER on an existing trigger.
The following restrictions apply to AFTER triggers:
AFTER triggers can be placed only on tables, not on views.
A single AFTER trigger cannot be placed on more than one table.
The text, ntext, and image columns cannot be referenced in the AFTER trigger logic.