Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / web / ASP.NET

Send Email Alert on Database Schema Change in SQL Server

4.75/5 (17 votes)
4 Oct 2013CPOL4 min read 50.9K   12  
Auto Monitoring On Schema Change within Database in SQL Server and Email Alert

Introduction

How Can We Keep Close eyses on Monitoring Schema Change in Any Database of SQL Server? How Can we keep track of these changes and Send Alert Email to Concern Persons to Inform About this change?

This is a kind of Administrator Activity Which We will learn in this Article. For this You Need to have SQL Mail Profile Configured in your SQL Server to send Email Alert From SQL Server.

Scenario

When Multiple Developer works on a Project and they do changes in database schema very frequently in initial phase of development at that time it will be difficult for the SQL or BI Developer who is associated with creation of Data Archival ETL. Change in base tables Schema can lead to Scheduled Job Failure due to alteration in column data type or size, or will loose information from newly added column if release was not properly planned. It is also possible someone can do change without any release note. so to avoid this all problems we can create Alert to send Email to Concern Person whenever any change in database schema takes place.

Here is Solution of the Problem

We First Create a Table which will be used to store records of DML Script used to change database Schema.

Then We will use System Level Trigger to Observe changes in schema in any database of SQL Server and Insert Record in above table with Script command used for Data Manuplation Operation(DML) , this way we can keep track of history of Schema changes done Over a period of time.

At last We Create Trigger on above Table which will Send Email to Admin to inform about change in Schema whenever new record get inserted.


Step 1 : Create Database (DBAdmin) In Your SQL Server.

Create Database DBAdmin
Go

Step 2 : Create Table(DBSchema_Change_Log) in Database (DBAdmin)

Select Database DBAdmin -->Execute Below Script to Create Table ( DBSchema_Change_Log).

USE [DBAdmin] 
GO
/****** Object:  Table [dbo].[DBSchema_Change_Log]    Script Date: 3-Oct-2013 14:38:02 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SET ANSI_PADDING ON
GO
CREATE TABLE [dbo].[DBSchema_Change_Log](
    [RecordId] [int] IDENTITY(1,1) NOT NULL,
    [EventTime] [datetime] NULL,
    [LoginName] [varchar](50) NULL,
    [UserName] [varchar](50) NULL,
    [DatabaseName] [varchar](50) NULL,
    [SchemaName] [varchar](50) NULL,
    [ObjectName] [varchar](50) NULL,
    [ObjectType] [varchar](50) NULL,
    [DDLCommand] [varchar](max) NULL
    
) ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO

Step 3 : Create Trigger at Server Level and Enable it.

Create System Level Trigger (Schema_LogInTable_DDL ) , so whenever change (Create / Alter/ Drop) occur in any database Schema so it will insert Event detail with script command used.

EVENTDATA function to create a log of events, Returns xml information about server or database events. this function is called when an event notification fires, and the results are returned to the specified service broker. EVENTDATA can also be used inside the body of a DDL or logon trigger.

Here we have used Variable of XML Datatype (@eventInfo) to store resultset returned by Eventdata function and used Query Method to retrieve Values of Resultset from Variable.

Query

Result

('data(/EVENT_INSTANCE/PostTime)')),'T', ' ')

Event Occurrence Time, When Command Executed

('data(/EVENT_INSTANCE/LoginName)')

Gives you Login Name used while Execution of Script

('data(/EVENT_INSTANCE/DatabaseName)'

Database Name On Which change Occured

('data(/EVENT_INSTANCE/SchemaName)')

Schema Name of the Database

(data(/EVENT_INSTANCE/ObjectName))

Name Of the Object e.g. TableName

(data(/EVENT_INSTANCE/ObjectType)')

Type Of the Object e.g Table

(data(/EVENT_INSTANCE/TSQLCommand/CommandText)')

T-SQL Command used to change the Schema


--Create trigger on system level which can keeps note down changes in any database and insert record in specified table
/****** Object:  DdlTrigger [[SchemaChange_LogInTable_DDL]]    Script Date: 03-Oct-2013 14:36:30 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
CREATE TRIGGER [SchemaChange_LogInTable_DDL]
 
ON ALL SERVER 
 
FOR CREATE_TABLE, ALTER_TABLE, DROP_TABLE
 
--Fires only for CREATE / ALTER / DROP Table
 
AS 
DECLARE       @eventInfo XML
 
SET           @eventInfo = EVENTDATA()
 
 
INSERT INTO DBAdmin.dbo.DBSchema_Audit_Log  VALUES
 
(

 
       REPLACE(CONVERT(VARCHAR(50),@eventInfo.query('data(/EVENT_INSTANCE/PostTime)')),'T', ' '),
 
       CONVERT(VARCHAR(50),@eventInfo.query('data(/EVENT_INSTANCE/LoginName)')),
 
       CONVERT(VARCHAR(50),@eventInfo.query('data(/EVENT_INSTANCE/UserName)')),
 
       CONVERT(VARCHAR(50),@eventInfo.query('data(/EVENT_INSTANCE/DatabaseName)')),
 
       CONVERT(VARCHAR(50),@eventInfo.query('data(/EVENT_INSTANCE/SchemaName)')),
 
       CONVERT(VARCHAR(50),@eventInfo.query('data(/EVENT_INSTANCE/ObjectName)')),
       CONVERT(VARCHAR(50),@eventInfo.query('data(/EVENT_INSTANCE/ObjectType)')),
 
       CONVERT(VARCHAR(MAX),@eventInfo.query('data(/EVENT_INSTANCE/TSQLCommand/CommandText)'))
 
) 
GO
SET ANSI_NULLS OFF
GO
SET QUOTED_IDENTIFIER OFF
GO
--Enable the Trigger on all server so it will run whenever change occur in schema on any database
ENABLE TRIGGER [SchemaChange_LogInTable_DDL] ON ALL SERVER
GO
GO  

Step 4 : Create Trigger On Table DBSchema_Change_Log in database DBAdmin

Create Trigger on Table (DBSchema_Change_Log) for insert and update whenever new record inserted or updated in this table it will send Email Alert to concer person.

Here we have done Formating of Message to create HTML Body of Email.

--create trigger on your above table which will send you email

USE [DBAdmin] 
GO
/****** Object:  Trigger [dbo].[SchmaChangeNotification]    Script Date: 03-Oct-2013 14:37:39 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

Create TRIGGER [dbo].[SchmaChangeNotification] 
   ON  [DBAdmin].[dbo].[DBSchema_Change_Log] 
   AFTER INSERT,UPDATE
   AS 
BEGIN

SET NOCOUNT ON;

DECLARE @Body NVARCHAR(MAX)
Declare @mailbody Nvarchar(max)

SET @Body = CAST(( SELECT top 1 X.RecordID AS 'td','',X.EventTime AS 'td','',X.LoginName AS 'td','',x.UserName AS 'td','',
       x.DatabaseName AS 'td','',x.SchemaName AS 'td','', x.ObjectName AS 'td','', x.ObjectType AS 'td','', x.DDLCommand  AS 'td',''
       from  DBSchema_Change_Log X order by X.RecordID desc
       FOR XML PATH('tr'), ELEMENTS ) AS NVARCHAR(MAX))


 
SET @mailbody =  '<html><body>'+@Body +'</body></html>'


--print @mailbody
--Code Start for Sending Email using SQL Email Profile
EXEC msdb.dbo.sp_send_dbmail
@profile_name = 'SQLProfile_Mail_Live', -- replace with your SQL Database Mail Profile 
@body = @mailbody,
@body_format ='HTML',

@recipients = 'mubin4all@gmail.com;', -- replace with your email address
@subject = 'Schema Change Notification' ;
--Code End for sending Email
END 

Observer different Objects Created in Object Explorer of SQL Server Management Studio.

1. You can See Database DBAdmin

2. (DBSchema_Change)Table Within DBAdmin

3. (Schema Change Notification) Trigger On Table (DBSchema_Change)

4. (SchemaChange_LoginTable_DDL) Server level Trigger under Server Objects

Image 1

Do the Testing of All Above Configuration Now

If you have not configured SQL mail Profile then simply comment the TSQL Query used for sending Email in Step 4 it is placed betweeb start and end comment.

C++
use DBAdmin 
go
--Create sample table to check Trigger on system level fires or not
create table TestTable
(
name varchar(100)
)
go
-- View Record Logged by trigger with SQL Script 
select * from [DBSchema_Change_Log]

Output Result

Image 2

Here you are ready to do monitoring on your SQL Server, If You Like this Article Please Do Not Forget to Vote For Me..

Credits

Source code contains reference to the following where appropriate

Copyright

By uploading my code to codeproject.com I assume I inherit all open source terms of use, licenses and those specified by codeproject.com. However if you use this code for any purpose I would really like to hear about it. It is my belief that by referencing the credited people I demonstrate the ability to effectively read and re-use source code, rather than re-invent the wheel. I expect you would do the same.

Enjoy SQLization.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)