Introduction
Sometimes one need to discover if a database has changed and,, if so, what tables has changed. Normally it can be done with log analysis. However if database size is not too big, it is easier to use this code.
Using the code
I've written a Microsoft SQL Server Stored Procedure for calculating checksum for all tables in the current database or just for some tables. The procedure returns a integer number based on all fields using the
physical order.
It uses the native Checksum function from Microsoft SQL Server. The user can optionally specify a file model. If one notice that data has changed,, one can view the detailed logs for more details.
Syntax
CheckSumDB @Verbose
[ @Exit
<code>
@TabExit @Model ]
@Verbose
: H - This help.
R - It shows final checksum (default)
A - It shows checksum for all tables
N - No output
@Exit
: Result output
@TabExit
: Output Table with Table name and Checksum fields
@Model
: Substring that Table name should contain. Default all
Example
Exec CheckSumDB N, @Check Output, 'Tb_Checksum'
Source Code
Create PROCEDURE CheckSumDB
@Verbose Char(1)='R',
@Exit Int=0 OutPut,
@TabExit varchar(20)='',
@Model varchar(20)=''
AS
Begin
Declare @Tot Bigint
Declare @Conta Int
Declare @CS Int
Declare @Aux Int
Declare @Tabela Varchar(30)
Declare @SQL NVarChar(1000)
Declare @Params NVarchar(30)
Declare @HasFile Bit
Declare @HasModel Bit
Declare @File NVarchar(30)
Declare @Mess Varchar(25)
Set NoCount On
Set @Verbose = Upper(@Verbose)
if @Verbose='?' or @Verbose='H'
begin
Print 'CheckSumDB - Return checksum as a integer, in order to check'
Print ' if there was any changes between two distinct moments.'
Print ''
Print 'SYNTAX: CheckSumDB @Verbose [ @Exit @TabExit @Model ]'
Print ' @Verbose : H - This help'
Print ' R - It shows final checksum (default)'
Print ' A - It shows checksum for all tables'
Print ' N - No output'
Print ' @Exit : Result output'
Print ' @TabExit : Output Table with Table name and Checksum fields'
Print ' @Model : Substring that Table name should contain. Default all'
Print ''
Print 'Example:'
Print ' Exec CheckSumDB N @Check Output - Calculates checksum for database'
Print ' returning in the @Check variable, with no messages'
Return
end
Set @HasFile = Case When @TabExit='' Then 0 Else 1 End
Set @HasModel = Case When @Model='' Then 0 Else 1 End
Set @Tot=0
Set @Conta=0
IF @HasFile=1
begin
Set @File = quotename(@TabExit)
Set @Sql = N'if object_id(''dbo.' + @File +
N''') is not null Drop Table ' + @File +
N' Create Table ' + @File +
N' (Tab varchar(30), CheckS Int)'
Exec sp_executesql @Sql
end
Declare C Cursor Fast_Forward
For
SELECT O.Name As Tabela
From sysobjects As O
INNER JOIN sys.partitions As p
On O.id=P.object_id
WHERE O.XType='U' and p.index_id IN (0, 1) and P.rows>0
OPEN C
WHILE 1=1
begin
FETCH NEXT FROM C INTO @Tabela
IF @@FETCH_STATUS <> 0 Break
IF ( @Model='' OR @Tabela LIKE '%' + @Model + '%' ) and (@Tabela <> @TabExit)
begin
Set @Sql= N'Select @Aux = Avg(Cast(CHECKSUM(*) As Float)) From dbo.' +
QuoteName(@Tabela)
Set @Params = N'@Aux Int OUTPUT'
Exec sp_executesql @Sql, @Params, @Aux = @Aux Output
Set @CS = Abs(Floor(@Aux))
IF @HasFile=1
begin
Set @Sql = N'Insert Into ' + @File + N' Select @Tabela , @CS'
Set @Params = N'@Tabela Varchar(30), ' + N'@CS Int'
Exec sp_executesql @Sql, @Params, @Tabela, @CS
end
if @verbose = 'A'
Print 'Checksum for table ' + @Tabela + ': ' +
Replace(Convert(Varchar,CONVERT(Money,@CS),1), '.00','')
Set @Conta = @Conta + 1
Set @Tot = @Tot + @CS
end
end
CLOSE C
DEALLOCATE C
if @Conta=0
Set @Exit=0
else
Set @Exit =Floor( @Tot / @Conta )
if @verbose = 'A' or @verbose='R'
if @Conta=0
Print 'No files found'
else
begin
Set @Mess = Replace(Convert(Varchar,CONVERT(Money,@Exit),1), '.00','')
if @Model=''
Print 'Database Checksum: ' + @Mess
else
Print 'Checksum for model ' + @Model + ': ' + @Mess
end
end
Points of Interest
It's a nice example of advanced dynamic SQL programming with Sysobjects
use.