YOUR FEEDBACK
Jeremy Geelan wrote: In response to inquiries and suggestions from readers this lexicon has recently...

SYS-CON.TV
TOP MICROSOFT .NET LINKS


DDL Triggers
Monitor and control changes in SQL Server 2005

A number of years ago, I worked for a company that was developing internal applications with SQL Server 2000. We didn't have any real database administrators. I was given that responsibility, but I was really a developer, one of many in fact. The problem with this arrangement was that all the developers had high-level rights to SQL Server. Each one could make whatever changes seemed appropriate to him at the time, and they could do this without consulting me. This often resulted in data incompatibilities that caused a bit of downtime, but lots of irritation. One day, however, my frustration reached a peak when some developer accidentally deleted a table that was used by a large number of applications. No one would take responsibility for the deletion, and so, predictably, I was expected to find out who did it. I did manage to do it, but it took a while and lots of SQL Profiler traces (I couldn't identify the culprit, so I had to catch him making the same mistake again). I remember thinking, "I wish I could easily prevent certain changes to the database, but allow others. I also wish I could log all the structure changes without having to resort to Profiler."

Today, my wish has been fulfilled.

SQL Server 2005 supports DDL Triggers. DDL Triggers are triggers that fire in response to data definition language (DDL) statements such as CREATE TABLE or UPDATE STATISTICS. They're similar to the data manipulation language (DML) triggers that we've been using for years, except that they're tied to a database or server instead of a table or view. With DDL Triggers we can write code that runs in response to changes made to server and database objects. This can be a very powerful tool. (It becomes even more powerful when used with SQL Server's CLR Integration feature, which allows SQL Server objects to be created with our choice of .NET language.) DDL Triggers can be used for many purposes, but most commonly for change tracking and prevention.

This article introduces DDL Triggers and shows how to use them to track and prevent changes to database objects. We'll discuss trigger creation, trigger deletion, and trigger security. We'll also walk through some examples of typical DDL Trigger use. Along the way, we'll see how we can use XQuery to retrieve specific information about the event that caused the trigger to fire. Although a thorough knowledge of XQuery isn't critical, it's definitely beneficial. You might want to refer to SQL Server Books Online for more information.

Managing DDL Triggers
DDL Triggers are managed in much the same way that DML Triggers are managed. You use the CREATE TRIGGER, ALTER TRIGGER, and DROP TRIGGER statements. As you might expect, however, there are subtle differences. The first difference is scope. DML Triggers work against a particular table or view, but DDL Triggers work against a database or server. When managing DDL Triggers, you use the ON DATABASE clause or the ON ALL SERVER clause to specify the scope. Next, DDL Triggers fire in response to particular events or groups of events. You use the FOR clause to specify them. Another important difference is that DDL Triggers can't be declared with the INSTEAD OF clause because these triggers can't fire instead of the indicated event like DML Triggers can. A final, but important, difference is that the ON DATABASE or ON ALL SERVER clause must be specified in all CREATE TRIGGER, ALTER TRIGGER or DROP TRIGGER statements. If you don't specify one of these clauses, SQL Server will assume that you are referring to a DML Trigger instead of a DDL Trigger. Your statement will then fail to work properly.

Let's walk though an example. In Listing 1 you can see the T-SQL code that creates a trigger that will fire in response to any DROP TABLE statement that is executed in the AdventureWorks database. The CREATE TRIGGER statement contains the ON DATABASE clause, which indicates that the scope of the trigger is the current database. The FOR DROP_TABLE clause specifies that the trigger should fire in response to a DROP TABLE statement. (See "DDL Events for Use with DDL Triggers" in the SQL Server 2005 Books Online for a list of available DDL events.) In the trigger body, I've included a PRINT statement and a ROLLBACK TRANSACTION statement. This trigger will print an explanatory message and then roll back the current transaction. This effectively "prevents" any DROP TABLE statement from executing. Listing 1 also contains code to create and drop a test table. Because of the trigger, the DROP TABLE statement will fail, producing the output shown in Listing 2. (See Figure 1 for an example of the output produced by a DROP TABLE command issued inside SQL Server Management Studio.) Next, the code drops the trigger (note the ON DATABASE clause) and then successfully drops the test table.

Auditing Changes
The previous example "prevented" changes by rolling back the transaction that caused them. While this works well, it's not always what's needed. Sometimes we want to allow changes, but we must have a record of what changes were made and who made them. DDL Triggers make this easy. In Listing 3, I've written code that creates a trigger that records information about any change made to the AdventureWorks database. This code is more complex so let's walk through it a little more slowly. First, I create a table to hold the desired audit information. In this case, I want to know which command was executed by which user and at what time. Next, I create the trigger. Once again, I use the ON DATABASE clause to specify the current database as the trigger scope. Next, however, I use the ON DDL_DATABASE_LEVEL_EVENTS clause to specify that this trigger should fire in response to any change event in the entire database. (This demonstrates the power of Event Groups. See "Event Groups for Use with DDL Triggers" in the SQL Server 2005 Books Online for a list of available DDL event groups.) The trigger body performs three tasks. First, it uses the EVENTDATA function to obtain an XML document that contains information about the event that caused the trigger to fire. The EVENTDATA function returns this data as an instance of the XML data type, and this data is stored in the @Data variable. Next, the QUERY method is used to get specific pieces of information from the XML document stored in the @Data variable. (The QUERY method is one of the five methods provided by the XML data type. This particular method accepts an XQuery query string, and returns an instance of the XML data type.) This process is repeated twice; once to get the text of the executed command (//TSQLCommand/CommandText), and once to get the time when the command was executed (//PostTime). The standard SYSTEM_USER function provides the name of the user who invoked the command. Finally, the collected information in inserted into the DDLAudit table.

The rest of the code in Listing 3 tests the trigger. A test table is created and dropped and then the contents of the DDLAudit table are shown. See Figure 2 for the results. You can see the commands that were executed, the user who executed the commands, and the time when the commands were executed.

Permissions
You may be wondering how all of this helps. If a developer has permission to create and drop tables, why can't he or she disable the database-scoped trigger before a change and re-enable it afterwards? The answer is that different permissions are needed for these actions. I can grant a developer full rights to a database, but deny him or her the ALTER ANY DATABASE DDL TRIGGER permission. The developer will then be able to make practically any change to the database, but not be able to affect the trigger that logs those changes. Similarly, managing server-scoped triggers requires the CONTROL SERVER permission. Users lacking the proper permissions won't be able to delete or disable the DDL triggers.

Summary
DDL Triggers bring a new level of control to SQL Server 2005. They allow code to run when changes are made to database-level objects such as tables, roles, or stored procedures. They also let code run when changes are made to server-level objects such as logins, endpoints, and databases. The triggers can perform actions ranging from change prevention (ROLLBACK TRANSACTION) to change auditing (storing change information in a table) and notification (sending an e-mail to the DBA when a change is made). In addition, because DDL Trigger management requires its own set of permissions, developers with high-level rights can be prevented from deleting or overriding the triggers.

To return to my story. If DDL Triggers had been available in SQL Server 2000, I could have implemented a trigger that would have stopped the developer from deleting that important table. The trigger could also have logged the attempt and maybe even notified me straightaway. We would have saved time, data, and a lot of frustration. You can bet that I'll be implementing DDL triggers in my next enterprise database.

About Jerry Dixon
Jerry Dixon is a senior developer and architect for ACH Food Companies in Memphis, Tennessee. Over the past 16 years he has led development projects for a number of enterprise, mid-level, and small business organizations. While he has fulfilled multiple roles as an infrastructure designer, database administrator, and software developer, he specializes in XML, SQL and ASP.NET. He is a co-leader and frequent presenter at the Memphis .NET User Group. Jerry holds the following Microsoft certifications: MCSD (VB 6.0 and .NET), MCDBA (SQL 2000), MCSA (Windows 2000 and 2003), MCSE (Windows 2000), MCAD (.NET), MCT. He resides in Olive Branch, MS with his wife and son.

MICROSOFT .NET LATEST STORIES
Many of today (and tomorrow’s) development projects lend themselves nicely to RIA application patterns. Silverlight offers a compelling RIA development experience that works on Linux, the Mac and windows as well as all major browsers. With HD video, vector based graphics and a rich s...
As a long-time PB developer, I have successfully created or maintained many PB applications for clients and for myself. Since day one, I was impressed with the ease with which applications can be created using PowerBuilder. Although I had been exposed to Visual Studio and other client/...
TeamExpand, a developer of products complimentary to Microsoft Visual Studio Team System (VSTS), announced the commercial version of its TX Chrono, a timesheet tracking application targeted at software development organizations standardizing on the Visual Studio .NET environment. Besid...
China’s new anti-monopoly law went into effect August 1 and China-based Evermore Software, an Office wannabe, would love to haul Microsoft into court. It says it’s collecting evidence and has suggested to MarketWatch that the integration between Office and Windows might be just...
Developer Express announced the immediate availability of its reporting platform for WinForms and ASP.NET – the XtraReports Suite v2008 vol 2. Built and optimized for Visual Studio, the DevExpress suite of reporting components allows software developers to deliver cutting-edge capabi...
SUBSCRIBE TO THE WORLD'S MOST POWERFUL NEWSLETTERS
SUBSCRIBE TO OUR RSS FEEDS & GET YOUR SYS-CON NEWS LIVE!
Click to Add our RSS Feeds to the Service of Your Choice:
Google Reader or Homepage Add to My Yahoo! Subscribe with Bloglines Subscribe in NewsGator Online
myFeedster Add to My AOL Subscribe in Rojo Add 'Hugg' to Newsburst from CNET News.com Kinja Digest View Additional SYS-CON Feeds
Publish Your Article! Please send it to editorial(at)sys-con.com!

Advertise on this site! Contact advertising(at)sys-con.com! 201 802-3021


SYS-CON FEATURED WHITEPAPERS

ADS BY GOOGLE
BREAKING NEWS FROM THE WIRES

The Consumer Electronics Association (CEA)®<...