CHAPTER 30 Creating and Managing Triggers --update the data related to the jobs table UPDATE jobs SET jobs.min_lvl = i.min_lvl, jobs.max_lvl = i.max_lvl, jobs.job_desc = i.job_desc FROM
Trang 1CHAPTER 30 Creating and Managing Triggers
update the data related to the jobs table
UPDATE jobs
SET jobs.min_lvl = i.min_lvl,
jobs.max_lvl = i.max_lvl,
jobs.job_desc = i.job_desc
FROM inserted i
WHERE jobs.job_id = i.job_id
AND (jobs.min_lvl <> i.min_lvl
OR jobs.max_lvl <> i.max_lvl
OR jobs.job_desc <> i.job_desc)
update the data related to the employee table
UPDATE employee
SET employee.job_lvl = i.min_lvl
FROM inserted i
WHERE employee.emp_id = i.emp_id
GO
A section in Listing 30.13 checks the fields related to the jobs table and updates the base
table if any of the values have changed Another section updates the employee table for
the employee fields that have been changed in the view
NOTE
You could enhance the trigger in Listing 30.13 to include logic to check for specific
updates or to update only those employees who are assigned to the job and have a job
level below the new minimum These enhancements are not included in the listing to
keep the example simple
If you now execute the same UPDATE statement, you don’t get an error message:
UPDATE employeeJobs
SET min_lvl = 40,
job_lvl = 40
WHERE job_id = 12
GO
The following results show values selected from the employeeJobs view after the update is
executed successfully:
min_lvl max_lvl job_id job_desc job_lvl emp_id
- - - -
-25 100 14 Designer 35 ENL44273F
25 100 14 Designer 89 PSA89086M
Trang 225 100 14 Designer 100 KFJ64308F
25 100 13 Sales Representative 35 PMA42628M
25 100 13 Sales Representative 64 CGS88322F
25 100 13 Sales Representative 100 TPO55093M
40 100 12 Editor 40 Y-L77953M
40 100 12 Editor 40 H-B39728F
40 100 12 Editor 40 HAS54740M
Notice that the Editor job now has a minimum level (min_lvl) equal to 40 and that all
the employees who have that job level (job_lvl) are also set to 40
You can see the added flexibility that you get by using the INSTEAD OF trigger on a basic
view This flexibility is also applicable to a more sophisticated view called a distributed
partitioned view With this type of view, data for the view can be partitioned across
differ-ent servers Partitioning this way enables you to scale a database solution and still have a
single view of the data that appears as one table
You can make data modifications via a distributed partitioned view, but some restrictions
exist If you do not meet the requirements for updating the view, you can use the INSTEAD
OF trigger to bypass these restrictions; this is similar to adding an INSTEAD OF trigger on a
nonpartitioned view
INSTEAD OF Trigger Restrictions
INSTEAD OF triggers have many capabilities, but they also have limitations Following are
some of them:
INSTEAD OF triggers do not support recursion This means they cannot call
them-selves, regardless of the setting of the Recursive Triggers database option For
example, if an INSERT is executed on a table that has an INSTEAD OF trigger, and the
INSTEAD OF trigger performs an INSERT on this same table, the INSTEAD OF trigger for
this INSERT does not fire a second time Any AFTER triggers defined on the same
table for INSERT fire based on the INSTEAD OF trigger INSERT
You can define only one INSTEAD OF trigger for each action on a given table
Therefore, you can have a maximum of three INSTEAD OF triggers for each table: one
for INSERT, one for UPDATE, and one for DELETE
A table cannot have an INSTEAD OF trigger and a FOREIGN KEY constraint with CASCADE
defined for the same action For example, you cannot have an INSTEAD OF trigger
defined for DELETE on a given table as well as a foreign key with a CASCADE DELETE
definition You get an error if you attempt to do this In this situation, you could have
INSTEAD OF triggers defined on INSERT and UPDATE without receiving errors
Trang 3CHAPTER 30 Creating and Managing Triggers
Using DDL Triggers
DDL triggers were introduced in SQL Server 2005 These triggers focus on changes to the
definition of database objects as opposed to changes to the actual data The definition of
database objects is dictated by the DDL events that these triggers respond to
The DDL events that these triggers fire on can be broken down into two main categories
The first category includes DDL events that are scoped at the database level and affect the
definition of objects such as tables, indexes, and users The second category of DDL
trig-gers is scoped at the server level These trigtrig-gers apply to server objects, such as logins
The number of DDL events at the database level far exceeds the number at the server
level Table 30.2 lists the DDL statements and system stored procedures that DDL triggers
can fire on
TABLE 30.2 DDL Statements and System Stored Procedures*
Create/Grant/Bind/Add Alter/Update/Deny Drop/Revoke/Unbind
Statements and System Stored Procedures with Database-Level Scope
CREATE_APPLICATION_ROLE ALTER_APPLICATION_ROLE DROP_APPLICATION_ROLE
(sp_addapprole) (sp_approlepassword) (sp_dropapprole)
ALTER_AUTHORIZATION_
DATABASE (sp_changedbowner) CREATE_CERTIFICATE ALTER_CERTIFICATE DROP_CERTIFICATE
CREATE_EXTENDED_PROPERTY ALTER_EXTENDED_PROPERTY DROP_EXTENDED_PROPERTY
(sp_addextendedproperty) (sp_updateextendedproperty) (sp_dropextended
property) CREATE_FULLTEXT_INDEX ALTER_FULLTEXT_INDEX
DROP_FULLTEXT_INDEX (sp_fulltexttable) ( sp_fulltextcatalog) (sp_fulltexttable)
Trang 4TABLE 30.2 DDL Statements and System Stored Procedures*
Create/Grant/Bind/Add Alter/Update/Deny Drop/Revoke/Unbind
(sp_fulltext_column)
(sp_indexoption)
CREATE_MESSAGE_TYPE ALTER_MESSAGE_TYPE DROP_MESSAGE_TYPE
CREATE_PARTITION_FUNCTION ALTER_PARTITION_FUNCTION DROP_PARTITION_FUNCTION
CREATE_PARTITION_SCHEME ALTER_PARTITION_SCHEME DROP_PARTITION_SCHEME
(sp_create_plan_guide) (sp_control_plan_guide) (sp_control_plan_guide)
CREATE_REMOTE_SERVICE_ ALTER_REMOTE_SERVICE_ DROP_REMOTE_SERVICE_
RENAME
(sp_rename)
(sp_addrole and
sp_addgroup)
(sp_droprole and sp_dropgroup) ADD_ROLE_MEMBER ALTER_ROUTEDROP_ROLE_MEMBER
(sp_addrole and sp_adduser) (sp_changeobjectowner)
(sp_addgroup and
sp_grantdbaccess)
Trang 5CHAPTER 30 Creating and Managing Triggers
TABLE 30.2 DDL Statements and System Stored Procedures*
Create/Grant/Bind/Add Alter/Update/Deny Drop/Revoke/Unbind
CREATE_SYMMETRIC_KEY ALTER_SYMMETRIC_KEY DROP_SYMMETRIC_KEY
(sp_tableoption)
(sp_settriggerorder)
(sp_adduser and
sp_grantdbaccess)
(sp_change_users_login) (sp_dropuser and
sp_revokedbaccess)
CREATE_XML_SCHEMA_ ALTER_XML_SCHEMA_ DROP_XML_SCHEMA_
Statements and System Stored Procedures with Server-Level Scope
ALTER_AUTHORIZATION_
SERVER
(sp_fulltext_database) CREATE_ENDPOINT ALTER_ENDPOINTDROP_ENDPOINT
ALTER_INSTANCE
Trang 6TABLE 30.2 DDL Statements and System Stored Procedures*
Create/Grant/Bind/Add Alter/Update/Deny Drop/Revoke/Unbind
(sp_configure and
sp_addserver)
CREATE_LINKED_SERVER ALTER_LINKED_SERVER DROP_LINKED_SERVER
(sp_addlinkedserver) (sp_serveroption) (sp_dropserver)
CREATE_LINKED_SERVER_
LOGIN
DROP_LINKED_SERVER_
LOGIN
(sp_addlogin and
sp_grantlogin)
(sp_defaultdb and sp_defaultlanguage)
(sp_droplogin and sp_revokelogin (xp_grantlogin and
sp_denylogin)
(sp_password, sp_change_users_login)
(xp_revokelogin)
(sp_addmessage) (sp_altermessage) (sp_dropmessage)
CREATE_REMOTE_SERVER ALTER_REMOTE_SERVER DROP_REMOTE_SERVER
(sp_addserver) (sp_setnetname) (sp_dropserver)
Statements and System Stored Procedures with Database-Level Scope
Create/Grant/Bind/Add Alter/Update/Deny Drop/Revoke/Unbind
CREATE_APPLICATION_ROLE ALTER_APPLICATION_ROLE DROP_APPLICATION_ROLE
(sp_addapprole) (sp_approlepassword) (sp_dropapprole)
ALTER_AUTHORIZATION_
DATABASE(sp_changedbowner) CREATE_CERTIFICATE ALTER_CERTIFICATE DROP_CERTIFICATE
Trang 7CHAPTER 30 Creating and Managing Triggers
TABLE 30.2 DDL Statements and System Stored Procedures*
Create/Grant/Bind/Add Alter/Update/Deny Drop/Revoke/Unbind
CREATE_EXTENDED_
PROPERTY
ALTER_EXTENDED_PROPERTY DROP_EXTENDED_PROPERTY
(sp_addextendedproperty) (sp_updateextendedproperty) (sp_dropextendedproperty)
CREATE_FULLTEXT_INDEX ALTER_FULLTEXT_INDEX DROP_FULLTEXT_INDEX
(sp_fulltexttable) ( sp_fulltextcatalog) (sp_fulltexttable)
(sp_fulltext_column)
(sp_indexoption)
CREATE_MESSAGE_TYPE ALTER_MESSAGE_TYPE DROP_MESSAGE_TYPE
CREATE_PARTITION_FUNCTION ALTER_PARTITION_FUNCTION DROP_PARTITION_
FUNCTION CREATE_PARTITION_SCHEME ALTER_PARTITION_SCHEME DROP_PARTITION_SCHEME
(sp_create_plan_guide) (sp_control_plan_guide) (sp_control_plan_guide)
CREATE_REMOTE_SERVICE_BIN
DING
ALTER_REMOTE_SERVICE_BINDIN G
DROP_REMOTE_SERVICE_BIN DING
RENAME
(sp_rename)
(sp_addrole and
sp_addgroup)
(sp_droprole and sp_dropgroup)
Trang 8TABLE 30.2 DDL Statements and System Stored Procedures*
Create/Grant/Bind/Add Alter/Update/Deny Drop/Revoke/Unbind
(sp_addrole and sp_adduser) (sp_changeobjectowner)
(sp_addgroup and
sp_grantdbaccess)
CREATE_SYMMETRIC_KEY ALTER_SYMMETRIC_KEY DROP_SYMMETRIC_KEY
(sp_tableoption)
(sp_settriggerorder)
(sp_adduser and
sp_grantdbaccess)
(sp_change_users_login) (sp_dropuser and
sp_revokedbaccess)
CREATE_XML_SCHEMA_
COLLECTION
ALTER_XML_SCHEMA_COLLECTION DROP_XML_SCHEMA_
COLLECTION
Statements and System Stored Procedures with Server-Level Scope
ALTER_AUTHORIZATION_
SERVER
Trang 9CHAPTER 30 Creating and Managing Triggers
TABLE 30.2 DDL Statements and System Stored Procedures*
Create/Grant/Bind/Add Alter/Update/Deny Drop/Revoke/Unbind
(sp_fulltext_database)
ALTER_INSTANCE
(sp_configure and
sp_addserver)
CREATE_LINKED_SERVER ALTER_LINKED_SERVER DROP_LINKED_SERVER
(sp_addlinkedserver) (sp_serveroption) (sp_dropserver)
CREATE_LINKED_SERVER_
LOGIN
DROP_LINKED_SERVER_
LOGIN
(sp_addlogin and
sp_grantlogin)
(sp_defaultdb and sp_defaultlanguage)
(sp_droplogin and sp_revokelogin (xp_grantlogin and
sp_denylogin)
(sp_password, sp_change_users_login)
(xp_revokelogin)
(sp_addmessage) (sp_altermessage) (sp_dropmessage)
CREATE_REMOTE_SERVER ALTER_REMOTE_SERVER DROP_REMOTE_SERVER
(sp_addserver) (sp_setnetname) (sp_dropserver)
System stored procedures are enclosed in parentheses.
Trang 10Triggers created on the DDL events are particularly important for auditing purposes In
the past, it was very difficult to isolate changes to the definition of a database or to
secure them from change With DDL triggers, you have the tools necessary to manage
these changes
Creating DDL Triggers
The basic syntax for creating a DDL trigger follows:
CREATE TRIGGER trigger_name
ON { ALL SERVER | DATABASE }
[ WITH <ddl_trigger_option> [ , n ] ]
{ FOR | AFTER } { event_type | event_group } [ , n ]
AS { sql_statement [ ; ] [ n ] | EXTERNAL NAME < method specifier > [ ; ] }
The best way to illustrate the use of the DDL trigger syntax and power of these triggers is
to look at a few examples The example shown in Listing 30.14 illustrates the creation of a
DDL trigger that is scoped at the database level and prevents table-level changes
LISTING 30.14 A Database-Scoped DDL Trigger for Tables
CREATE TRIGGER tr_TableAudit
ON DATABASE
FOR CREATE_TABLE, ALTER_TABLE, DROP_TABLE
AS
PRINT ‘You must disable the TableAudit trigger in order
to change any table in this database’
ROLLBACK
GO
This trigger is fired whenever the CREATE, ALTER, or DROP TABLE statements are executed
Consider, for example, the following statements that can be run against the
BigPubs2008 database:
ALTER table titles
add new_col int null
alter table titles
drop column new_col
You must disable the TableAudit trigger in order to change any table in this
database
Msg 3609, Level 16, State 2, Line 1
The transaction ended in the trigger The batch has been aborted
These ALTER statements add a column to the titles table and then remove the column
With the tr_TableAudit trigger in place on the BigPubs2008 database, the error message is
displayed after the first ALTER statement is executed