I was asked following questions when discussing security issues in meeting with off-shore team of large database consultancy company few days ago. I will only discuss one of the security issue was discussed accidental data modification by developers and DBAs themselves.
How to alter modification in database by system admin himself?
How to prevent accidents due to fat fingers? (Accidental execution of code)
How to display message to contact another developers when another developer tries to modify object another developer working on?
It was interesting conversation. Answer to all the questions is correct assignment of permissions and (when permissions are not an issue) Server and Database Level DDL Triggers. If developers have their own login to SQL Server and it does not have permissions to drop or create objects this will not be issue at all. However, there are still risk of System Admin himself making accidental mistakes. The solution to this will be use Server and Database Level DDL Triggers.
DDL is abbreviation of Data Definition Level. DDL contains schema of the database object. It was always dream of all DBA, when change in mission critical schema of the database or server is attempted it is prevented immediately informing DBA and users automatically. DDL Trigger can now make this dream true. Definition of DDL Trigger (from BOL) is 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.
DML is abbreviation of Data Manipulation Level. DML contains the actual data which is stored in the database schema. UPDATE, INSERT, DELETE, SELECT are clause are used to manipulate database. There is following different between DML and DDL triggers.
- DDL triggers do not support INSTEAD OF feature DML triggers.
- DDL triggers do not have feature of inserted and deleted tables like DML triggers as it does not participate in database manipulations.
Following example demonstrates how DDL trigger can be used to prevent dropping stored procedure.
Step 1 :
First create any sample stored procedure.
USE AdventureWorks;
GO
CREATE PROCEDURE TestSP
AS
SELECT 1 test;
GO
Step 2 :
Create DDL trigger which will prevent dropping the stored procedure.
USE AdventureWorks
GO
CREATE TRIGGER PreventDropSP
ON DATABASE
FOR DROP_PROCEDURE
AS
PRINT 'Dropping Procedure is not allowed. DDL Trigger is preventing this from happening. To drop stored procedure run following script.
Script : DISABLE TRIGGER PreventDropSP ON DATABASE; <Run your DROP SP>; ENABLE TRIGGER PreventDropSP ON DATABASE;'
ROLLBACK;
GO
Step 3 :
Now test above trigger by attempting to drop the stored procedure.
USE AdventureWorks
GO
DROP PROCEDURE TestSP;
GO
This should throw following message along with error code 3609 :
Dropping Procedure is not allowed.
DDL Trigger is preventing this from happening.
To drop stored procedure run following script.
Script :
DISABLE TRIGGER PreventDropSP ON DATABASE;
<Run your DROP SP>;
ENABLE TRIGGER PreventDropSP ON DATABASE;
Msg 3609, Level 16, State 2, Line 1
The transaction ended in the trigger. The batch has been aborted.
Step 4 :
Now DISABLE above trigger and it will let you successfully drop the stored procedure previously attempted to drop. Once it is dropped enable trigger again to prevent future accidents.
USE AdventureWorks
GO
DISABLE TRIGGER PreventDropSP ON DATABASE;
DROP PROCEDURE TestSP;
ENABLE TRIGGER PreventDropSP ON DATABASE;
GO
List of all the DDL events (DROP_PROCEDURE in example above) to use with DDL Trigger are listed on MSDN.
If you want to download local copy click here.
Reference : Pinal Dave (http://www.SQLAuthority.com), BOL










DDL actually stands for Data Definition Language not Level. Sorry to be nit-picky, just wanted to clarify.
Hey Pinal!
I posted a comment on this entry yesterday and today it’s gone.
Did I do something wrong?
Hi Phillip,
I am not sure I receive more than 200 comments and 1000 of spams. I do not read any spams and delete them right away. Your comment can be categorized incorrectly.
However, when you post comment, you can immediately see them till it is approved by spam filter.
What is the comment about?
Kind Regards,
Pinal
Paul Nielsen has written a stored procedure that creates audit triggers for every table in your database.
Check out AutoAudit at http://www.sqlserverbible..com
can i dynamically generate the ddl for all of the sqlserver 2005 databases on the server, using a script.
thanks
How do you check the status of the trigger?
I wanted to know the trigger is enabled or disabled?
Look at the is_disable column in
select * from sys.triggers
where name=’your_trigger’
Hi Pinal
Iam new to triggers Sql server 2005.
Iam want to send a message to a user when data is inserted/updated to a table depending on a criteria. The data is comming from an external program which I ave no control to code. Can we capture the ip address as this is a multi user system. Do you have exapmles that i can use or look at.
Hi Pinal,
I have a trigger on a tracker table. Is there anything i can do so that others can not DISABLE that trigger? (In our organization, few S/W developers have access to DB). Or atleast, any way so that I can track the Enabling/Disabling that trigger ?
Thanks..
I use this to prevent people from modifying the DDL triggers:
–disable the trigger to add security exceptions
DISABLE TRIGGER [dba_trigger_log_db_events] ON DATABASE
GO
–get user names on the database
DECLARE @sqlCmd nvarchar(4000)
DECLARE curLoginsToDeny CURSOR FOR
SELECT ‘DENY ALTER ANY DATABASE DDL TRIGGER TO ['+[name]+’];’ [sqlCmd]
FROM sys.database_principals
WHERE [principal_id] > 4 — 0 to 4 are system users/schemas
and [type] IN (‘G’, ‘S’, ‘U’) –windows group, sql server login, windows user
and [name] NOT LIKE ”
OPEN curLoginsToDeny
FETCH NEXT FROM curLoginsToDeny INTO @sqlCmd
WHILE @@FETCH_STATUS = 0 –successful fetch
BEGIN
EXEC sp_executesql @sqlCmd –execute command to revoke rights
FETCH NEXT FROM curLoginsToDeny INTO @sqlCmd
END
CLOSE curLoginsToDeny
DEALLOCATE curLoginsToDeny
GO
–ENABLE the trigger after security exceptions are applied
ENABLE TRIGGER [dba_trigger_log_db_events] ON DATABASE
GO
This works well even for people who are DBO on the database. I also recommend using the WITH ENCRYPTION option:
CREATE TRIGGER [dba_trigger_log_db_events]
ON DATABASE
WITH ENCRYPTION
Hope that helps!
Thanks a lot Steve..
[...] Nested Trigger: A trigger can also contain INSERT, UPDATE and DELETE logic within itself, so when the trigger is fired because of data modification it can also cause another data modification, thereby firing another trigger. A trigger that contains data modification logic within itself is called a nested trigger. (Read More Here) [...]
Hi Pinal,
How can I make a Trigger that fires at 7:00 am every morning and excecutes a Stored procedure?
Do I need to make a Job for it or is there a better alternative?
Hi Megha,
You can not fire trigger as you execute Stored Procedure. Trigger will be automatically fire when INSERT/UPDATE/DELETE command executing on the table.
To execute Stored Procedure, you have to create JOB to run at that specific time.
Thanks,
Tejas
There is a database in a folder in C drive. when the folder exceeds 1MB A trigger is fired which transfer all these data into another folder in D drive. can anyone help me in this
I think you should use a windows scheduler to do this job
I need to create a basic ddl trigger that notifies on database creates, drops and alters. Nothing fancy because these databases are in a highly secure “nitch” – no database mail, not even a good way to get the results from one spot to another. I just need the info to either go to the default location, or a flat file. Don’t need to prevent. So far I’ve found this very easily:
CREATE TRIGGER tr_tableChange
ON DATABASE
FOR CREATE_TABLE, DROP_TABLE, ALTER_TABLE
AS
BEGIN
do some activity based on event
END
Is there a default, basic setup that logs to sys.events? This seems like it should be a lot simpler. :)
@russoaks
If you want something easy, then you can use osql commands to generate a text file on OS, When ever this trigger fires.
You will find plenty of examples for osql ( export or creating text file on OS)
If you need help, just leave a comment. Will be glad to help you out.
~ IM
Hi, I want to know how to execute local temporery procedure with example.. anyone help me..
Hi, your explanation is excellent.
In step 2, you provided details for security while droping the stored procedure.
Don’t we have security in tables also?
Pinal,
Since long time I am observing your blogs and your posts. First I appreciate your efforts to spend your valuable time nad made technology easier even for basic level developer.
Now come to the point, some where in this blog I have seen about cursors. In this you said cursor is a database object. I did lot of research how it become an object with out mangaing by dbms. If we see the execution engine of the SQL stateemnt i didnt see SQl is treating it as a object. Even microsoft also saying it as datatype.
For your reference:
http://msdn.microsoft.com/en-us/library/ms190498(SQL.90).aspx
If you provide your explanation that would be great.
I want to know one more thing. I am expecting some quick replys from you. Is there any way to post query for different area like that.
Ex: For SQL joins do i need to post in only SQL joins area ?
Thanks,
Srinivas Donavalli.
Is it possible to see all the triggers from information_schema
If you use version 2005, use
select * from sys.triggers
how to create a trigger to stop insert,update,detele commnds
Hello Niranjan,
Create INSTEAD OF trigger without any DML statement.
Regards,
Pinal Dave
hello sir,
can we pass parameter to trigger
No. It is not possible
Thank you sir.
Dear Sir i am using below code in Sql2005 and getting error . Please help me.
USE Test
GO
CREATE TRIGGER PreventDropSP
ON Test
FOR DROP_PROCEDURE
AS
PRINT ‘Dropping Procedure is not allowed.’
ROLLBACK;
GO
“”"Msg 170, Level 15, State 1, Procedure PreventDropSP, Line 6
Line 6: Incorrect syntax near ‘DROP_PROCEDURE’.”"”"”"
hai ved,
use test
go
create trigger preventdropsp
on database
for drop_procedure
as
print PRINT ‘Dropping Procedure is not allowed.’
ROLLBACK;
GO
Regards
kalyan
Hello Ved,
Write this as following:
CREATE TRIGGER PreventDropSP
ON DATABASE
FOR DROP_PROCEDURE
AS
PRINT ‘Dropping Procedure is not allowed.’
ROLLBACK;
GO
Regards,
Pinal Dave
Dear Sir
Thanks for your reply .However i am getting same error ..
Can you please give me any one of DDL Trigger Example.
Thanks
Ved
Hello,
I wish to track when anyone does INSERT,UPDATE, DELETE on any of the tables in a database. Is it possible to write database level trigger for this case?
Thanks,
-Saroj
hi sir i m creating trigger as
create trigger check_id
ON dbo.teacher
AFTER INSERT,UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF(t_no<100)
THEN
print('not allowed');
END;
but getting an error
Msg 156, Level 15, State 1, Procedure check_id, Line 8
Incorrect syntax near the keyword 'THEN'
pls. help me as ma a beginner in sql .
Hi,
There is an syntax error in the IF. check this out.
create trigger check_id
ON dbo.interest_rate
AFTER INSERT,UPDATE
AS
BEGIN
SET NOCOUNT ON;
IF(select Interest_rate from inserted) <100
print('not allowed')
END
Help Plz..
Well hello there.. i am facing problem in updating using trigger
following the trigger..
well my requirements is to update the column . I want to store(update) the prev. value while updating in another columns correspond to id.
like prevsal and newsalary.
following trigger which i have created…
*as we know when we update then (inserted and deleted will fire also in which the old value which we can retrieve using (select * from deleted))
ALTER trigger [dbo].[tb] on [dbo].[tb_name]
for insert, update
as
declare @count int
declare @loop int
declare @empid int
select @loop =1
select @count = (select * from tblname)
WHILE(@loop <= @count)
update tblname set newsalary=1200 where id=@loop and date='12/12/2010'
set @loop= @loop+1
update tblname set prevsal=(select newsalary from deleted)
End
*if there any Error then let me know well i am updating the field with column name newsalary but for column name prevsal they givng me NULL value except old value..
hope you can understand my requirement
with regards
vikram
[...] Nested Trigger: A trigger can also contain INSERT, UPDATE and DELETE logic within itself; so when the trigger is fired because of data modification, it can also cause another data modification, thereby firing another trigger. A trigger that contains data modification logic within itself is called a nested trigger. (Read more here) [...]
Hi Phillip,
I am trying to create a simple DDL trigger on server level, everything is fine on my local machine but when I am trying on our server (SQL 2005 Clustered) I am getting Error, any idea?
Create TRIGGER test
ON ALL SERVER
FOR DDL_DATABASE_LEVEL_EVENTS
AS
BEGIN
print ‘Hello’
END
Msg 1098, Level 15, State 1, Procedure test, Line 7
The specified event type(s) is/are not valid on the specified target object.
i want to execute the trigger whenever the new login is created i.e. new entry added to master..syslogins table ,
Which server trigger i need to have and whats the synatx and minimum permissions needed to create it , now i am security admin.
[...] Interview Questions and Answers ISBN: 1466405643 Page#24-25 Disadvantages (Problems) of Triggers Server and Database Level DDL Triggers Examples and Explanation Disable All Triggers on a Database – Disable All Triggers on All Servers Interesting Observation [...]
Hello.
Is it possible to create a trigger to insert, update and delete data from all tables of current database?
Something like this:
CREATE TRIGGER myTrigger
ON
FOR INSERT, UPDATE, DELETE
AS IF (@@ERROR 0)
BEGIN
INSERT into #tableSomething VALUES (1)
END
I’m using SQL Server 2008.
Thank you
TAP