Technical Article

Notification of schema changes - Advanced

,

This script modifies another excellent script written by SHAS3. The original script examines tables for changes and sends an email. This modification examines all stored procedures, tables, indexes, etc. in ALL databases or just the CURRENT database. If changes are detected, the script has the option to either email or log to a table that it will create for you. In addition, several performance enhancements are included as well as NOLOCK statements where appropriate to make it production ready.

/********************************************************************
Created by:     Shas3
Original: http://www.sqlservercentral.com/scripts/contributions/817.asp

Rewritten by: Brian Corrigan

Change Log:
9/28/2005 - Included log to table option, removed object cursor to improve efficiency, now includes option to examine all databases, examines all objects and not just tables

********************************************************************/

create procedure usp_dba_schema_ver_cntrl as
BEGIN 
 set nocount on

 declare @cmd varchar(8000)
declare @obj_name sysname
declare @db_name sysname
 declare @current_ver int
 declare @stored_ver int
 declare @current_crdate datetime
 declare @stored_crdate datetime
declare @cnt int
 declare @msg varchar(600)
 declare @status smallint
declare @logtoemail int
declare @logtotable int
declare @examinealldatabases int
 set @status = 0  -- successful status
declare @audittime datetime
set @audittime=current_timestamp

declare@subject varchar(255)
declare @messagevarchar(255)
declare @query  varchar(800)


--CONFIGURATION OPTIONS
--EMAIL and or SQL TABLE logging of results; 1 = YES, 0 = NO
set @logtoemail=0
set @logtotable=1

--ALL DATABASES or just CURRENT DATABASE; 1 = ALL, 0 = CURRENT
set @examinealldatabases = 1


if not exists (select name from sysobjects (NOLOCK) where name = 'dba_SchemaVerCntrl' and xtype = 'U')
create table dba_SchemaVerCntrl
([db_Name] sysname not null,
Obj_Name sysname not null,
 CreateDate datetime not null, 
 SchemaVersion int not null)
if @logtotable=1 
begin
if not exists (select name from sysobjects (NOLOCK) where name = 'dba_SchemaVerCntrlHistory' and xtype = 'U')
create table dba_SchemaVerCntrlHistory(
SummaryDate datetime, 
[db_Name] sysname not null,
Obj_Name sysname not null,
status char not null,
description varchar(50) null)
end


select @cnt = count(*) from dba_SchemaVerCntrl

IF @cnt = 0 and @examinealldatabases = 0
BEGIN
select @msg = 'Initializing dba_SchemaVerCntrl table with information from current DB'
print @msg

insert into dba_SchemaVerCntrl
select db_name(),name, Crdate, schema_ver 
from sysobjects (NOLOCK)

END
ELSE IF @cnt = 0 and @examinealldatabases = 1
BEGIN
select @msg = 'Initializing dba_SchemaVerCntrl table with information from all DBs'
print @msg

declare db_cursor cursor for 
select name from master..sysdatabases (NOLOCK)
WHERE name NOT IN ('master', 'model', 'tempdb', 'msdb', 'distribution') 

open db_cursor
fetch next from db_cursor into @db_name

WHILE @@fetch_status = 0
  BEGIN
select @query = 
'insert into dba_SchemaVerCntrl ' +
'select '''+@db_name+''', name, Crdate, schema_ver ' +
'from '+ @db_name +'..sysobjects (NOLOCK)'
Exec (@query)

fetch next from db_cursor into @db_name
END
  close db_cursor
  deallocate db_cursor

END
ELSE
BEGIN
--Create a temp table to hold all DB current schema
if exists (select name from sysobjects (NOLOCK) where name = '#dba_SchemaVerCntrl' and xtype = 'U')
drop table #dba_SchemaVerCntrlTemp

create table #dba_SchemaVerCntrlTemp
([db_Name] sysname not null,
Obj_Name sysname not null,
 CreateDate datetime not null, 
 SchemaVersion int not null)

--Populate the temp table with sysobjects from all databases
declare db_cursor cursor for 
select name from master..sysdatabases (NOLOCK)
WHERE name NOT IN ('master', 'model', 'tempdb', 'msdb', 'distribution') 

open db_cursor
fetch next from db_cursor into @db_name

WHILE @@fetch_status = 0
BEGIN
select @query = 
'select '''+@db_name+''', name, Crdate, schema_ver ' +
'from '+ @db_name +'..sysobjects (NOLOCK)'

insert into #dba_SchemaVerCntrlTemp
Exec (@query)

fetch next from db_cursor into @db_name
END
  close db_cursor
  deallocate db_cursor

--Create a temp table to record shema changes
declare @dba_SchemaVerCntrlChanges table
([db_Name] sysname not null,
Obj_Name sysname not null,
 CreateDate datetime not null, 
 SchemaVersion int not null,
changetype char
)

insert into @dba_SchemaVerCntrlChanges
--Find all new Records
select st.[db_name], st.obj_name, st.createdate, st.schemaversion, 'N'
from #dba_SchemaVerCntrlTemp st (NOLOCK)
left join dba_SchemaVerCntrl s (NOLOCK)
   on  st.[db_name]=s.[db_name] 
 and st.[obj_name]=s.[obj_name] 
where isnull(s.db_name,'')=''
UNION ALL
--Find all updated Records
select st.[db_name], st.obj_name, st.createdate, st.schemaversion, 'U'
from #dba_SchemaVerCntrlTemp st (NOLOCK)
join dba_SchemaVerCntrl s (NOLOCK)
   on  st.[db_name]=s.[db_name] 
 and st.[obj_name]=s.[obj_name] 
 and st.[schemaversion]<>s.[schemaversion]
UNION ALL
--Find all deleted Records
select s.[db_name], s.obj_name, s.createdate, s.schemaversion, 'D'
from #dba_SchemaVerCntrlTemp st (NOLOCK)
right join dba_SchemaVerCntrl s (NOLOCK)
   on  st.[db_name]=s.[db_name] 
 and st.[obj_name]=s.[obj_name] 
where isnull(st.db_name,'')=''


--Commit all changes to master schema version table, update history is log to table is on
begin transaction
--Update master shema version table for all changed objects
delete from dba_SchemaVerCntrl
insert into dba_SchemaVerCntrl
select * from #dba_SchemaVerCntrlTemp (NOLOCK)

--Record changes in history table
if @logtotable=1 
begin
insert into dba_SchemaVerCntrlHistory
select 
@audittime, 
[db_Name], 
Obj_Name, 
changetype,
case changetype 
 when 'N' then 'Created on ' + convert(varchar(24),createdate,109)
 when 'U' then 'Updated on ' + convert(varchar(12),@audittime,109)
 when 'D' then 'Deleted on ' + convert(varchar(12),@audittime,109)
 else 'Error'
end
from @dba_SchemaVerCntrlChanges
end 
commit transaction

--If log to email is on send the notification
IF @logtoemail=1 and (select count(*) from @dba_SchemaVerCntrlChanges) <> 0 
BEGIN
SELECT @subject = @@SERVERNAME + ' Database ' + DB_Name() +  ': Schema Control Report for ' + convert( varchar(20), GETDATE()) + char(34)
SELECT @message = @@SERVERNAME + ' Database ' + DB_Name() + ': Please find attached the Schema Control Report '

select @query = 
'select 
@audittime as AuditDate, 
[db_Name] as ''DatabaseName'', 
Obj_Name as ''Object Name'', 
case changetype 
 when ''N'' then ''Created on '' + convert(varchar(24),createdate,109)
 when ''U'' then ''Updated on '' + convert(varchar(12),@audittime,109)
 when ''D'' then ''Deleted on '' + convert(varchar(12),@audittime,109)
 else ''Error''
end
from @dba_SchemaVerCntrlChanges
order by [db_name], obj_name, changetype'

EXEC @status = master..xp_sendmail 
     @recipients = '<recipients>'
    ,@message = @message
    ,@subject = @subject
    ,@query   = @query
    ,@attach_results = 'false'
    ,@no_header = 'false'
    ,@echo_error = 'true'
    ,@width = 300
END  -- end send mail

drop table #dba_SchemaVerCntrlTemp
  
END  -- @cnt <> 0
 

IF @status <> 0
  return 1
 
 return 0
END


GO

Rate

You rated this post out of 5. Change rating

Share

Share

Rate

You rated this post out of 5. Change rating