Someone wanted to know when and by who a certain table was dropped, I told the person that you can do this with a DDL trigger.Wouldn’t it be nice if you could track exactly all the DDL statements that were executed on a table in your database? Well, you can by using DDL Triggers, DDL Triggers were added in SQL Server 2005.
DDL triggers are a special kind of trigger that fire in response to Data Definition Language (DDL) statements. They can be used to perform administrative tasks in the database such as auditing and regulating database operations. A DDL trigger can be created on the database level or on the server level. In this post I will create a database level DDL trigger that will listen for the ALTER TABLE command.
First I will create a sample database
CREATE DATABASE TestTrigger
GO
USE TestTrigger
GO
Now I will create a table which will hold the DDL statement, the time and the login of the person who executed the statement
CREATE TABLE TriggerLog(DDL VARCHAR(300), ExecutedBy VARCHAR(100), EventDate datetime)
GO
Here is what my DDL trigger will look like, more information about DDL triggers can be found here: http://msdn.microsoft.com/en-us/library/ms189799.aspx
CREATE TRIGGER trALterTable
ON DATABASE -- A DB level trigger
FOR ALTER_TABLE --Event we want to capture
AS
INSERT TriggerLog
SELECT EVENTDATA().value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]','nvarchar(max)'),
COALESCE(SUSER_SNAME(),USER_NAME()),
GETDATE();
GO
The code in the trigger should be pretty simple to follow. The line _EVENTDATA().value(‘(/EVENTINSTANCE/TSQLCommand/CommandText)1’,‘nvarchar(max)’) is grabbing the DDL statement, more about EVENTDATA() can be found here: http://msdn.microsoft.com/en-us/library/ms173781.aspx
Next up is the test table that we will use to play around with
CREATE TABLE test(id INT)
The following block of code will add a column, change the data type of the column and will finally drop the column
ALTER TABLE test
ADD SomeDate date
GO
ALTER TABLE test
ALTER COLUMN SomeDate datetime2
GO
ALTER TABLE test
DROP COLUMN SomeDate
GO
Now let’s see what we have in our log table
SELECT * FROM TriggerLog
order by EventDate
Here is the output
DDL | ExecutedBy | EventDate |
---|---|---|
ALTER TABLE test ADD SomeDate date | Denis-PCDenis | 2011-04-19 20:18:07.590 |
ALTER TABLE test ALTER COLUMN SomeDate datetime2 | Denis-PCDenis | 2011-04-19 20:18:09.900 |
ALTER TABLE test DROP COLUMN SomeDate | Denis-PCDenis | 2011-04-19 20:18:11.610 |
As you can see we have all the DDL statements captured in the table, the time it happened and the person who did it.
Let’s just drop and recreate the table
drop table Test
GO
Now create the table again
CREATE TABLE test(id INT)
GO
If you now execute this query, you will get back pretty much all the DDL statements that we executed before
SELECT DDL + 'GO'
FROM TriggerLog
ORDER BY EventDate
Here is what it looks like if you copied the results and pasted them into a query window.
ALTER TABLE test
ADD SomeDate date
GO
ALTER TABLE test
ALTER COLUMN SomeDate datetime2
GO
ALTER TABLE test
DROP COLUMN SomeDate
GO
This was just a small example of how a DDL trigger works, A DDL trigger enables you to also not allow ALTER TABLE statements during business hours or for certain user even though they are db owner.
To see all the events that DDL triggers can listen for you can use the sys.trigger_event_types Object Catalog View
select type_name from sys.trigger_event_types
Here is a partial result set
——————–
CREATE_TABLE
ALTER_TABLE
DROP_TABLE
CREATE_INDEX
ALTER_INDEX
DROP_INDEX
CREATE_STATISTICS
UPDATE_STATISTICS
DROP_STATISTICS
CREATE_SYNONYM
DROP_SYNONYM
CREATE_VIEW
ALTER_VIEW
DROP_VIEW
CREATE_PROCEDURE
*** Remember, if you have a SQL related question, try our Microsoft SQL Server Programming forum or our Microsoft SQL Server Admin forum