Technical Article

Compare the structure & code of 2 databases

,

We often make changes in the test databases. But failure in making even the smallest change in the production database may lead to unwanted situations.

This utility compares 2 databases.
Parameters to be passed  
@DB1  Database 1 (SysName) 
@DB2  Databse 2 (SysName) 
@ShowDifferentOnly see later (Bit) 
    
Parameters 1, 2 may include server name as  well.
But the server should be either local or linked server.
This Procedure is devided into 2 parts 
Part I Checks the tables and Views (Column Definition, size, default) etc. 
Part II Checks the Code of Views, Stored Procedures and Triggers 
If @ShowDifferentOnly is set to 1 it will show only the lines that are different 
Otherwise all lines of both objects are shown. 
Default for @ShowDifferentOnly is 1 

Tested in SQLServer 2000 Service Pack 1. 

Known Issues:
If Server name or the database name is with space, it should be included with single Quote and not with braces ([]). This procedure is not checking for the braces in the name.

Note:
This procedure does not check the data. Only the structure is checked.

Use Master
IF EXISTS(SELECT * FROM SYSOBJECTS WHERE NAME = 'sp_Compare2DB' and ObjectProperty(ID, 'ISPROCEDURE')=1)
DROP PROCEDURE sp_Compare2DB
GO

-- sp_Compare2DB  
--
-- Compares the structure of 2 databases of SQL Server
-- parameters to be passed   
-- @DB1  Database 1 (SysName)  
-- @DB2  Databse 2 (SysName)  
-- @ShowDifferentOnly see later (Bit)  
--      
-- Parameters 1, 2 may include server name as  well. 
-- But the server should be either local or linked server.
-- This Procedure is devided into 2 parts  
-- Part I Checks the tables and Views (Column Definition, size, default) etc.  
-- Part II Checks the Code of Views, Stored Procedures and Triggers  
-- If @ShowDifferentOnly is set to 1 it will show only the lines that are different  
-- Otherwise all lines of both objects are shown.  
-- Default for @ShowDifferentOnly is 1  
--
-- Tested in SQLServer 2000 Service Pack 1.  
--
-- Known Issues:
-- 1.If Server name or the database name is with space, 
-- it should be included with single Quote and not with braces.
-- This procedure is not checking for the braces in the name.
-- 2.This procedure is not checking the following:
--Indexes 
-- Primary Keys 
--Foreign Keys 
--Contraints
-- rules 
--user deined data types 
--Formula differents for computed columns
--
-- Note:
-- The purpose of this procedure is not to check the data. Only the structure is checked. 
--
--
--------------------------------------------------------------------------------------------
-- Written By G.R. Preethiviraj Kulasingham
-- Last Modified on 26th March 2002.
--------------------------------------------------------------------------------------------


CREATE  Procedure sp_Compare2DB     
@DB1 sysname, @DB2 sysname, @ShowDifferentOnly bit =1
AS      

Declare @SQL varchar(8000),       
 @Text nvarchar(4000),      
 @BlankSpaceAdded   int,       
 @BasePos       int,      
 @CurrentPos    int,      
 @TextLength    int,      
 @LineId        int,      
 @AddOnLen      int,      
 @LFCR          int, 
 @DefinedLength int,      
 @SyscomText nvarchar(4000),      
 @Line nvarchar(1000),    
 @ProcID int,      
 @ObjID int,      
 @ObjID2 int,      
 @OldProcID int,        
 @DBName1 SysName,
 @SvrName1 SysName,
 @DBName2 SysName,
 @SvrName2 SysName
    
Set NoCount on      
      
SET @DefinedLength = 1000
SET @BlankSpaceAdded = 0       
-- This Part Validated the Input parameters
set @DB1 = RTRIM(LTRIM(@DB1))
set @DB2 = RTRIM(LTRIM(@DB2))
set @SvrName1 = @@SERVERNAME
IF CHARINDEX('.',@DB1) > 0
begin
set @SvrName1 = LEFT(@DB1,CHARINDEX('.',@DB1)-1)
if not exists (select * from master.dbo.sysservers where srvname = @SvrName1)
begin
print 'There is no linked server named '+@SvrName1+' Found. Precedure Terminates.'
return 
end
set @DBName1 = RIGHT(@DB1,LEN(@DB1)-CHARINDEX('.',@DB1))
end
else
set @DBName1 = @DB1
exec ('declare @Name sysname select @Name=name from ['+@SvrName1+'].master.dbo.sysdatabases where name = '''+@DBName1+'''')
if @@rowcount = 0
begin
print 'There is no database named '+@DB1+' Found. Precedure Terminates.'
return 
end
set @SvrName2 = @@SERVERNAME
if CHARINDEX('.',@DB2) > 0
begin
set @SvrName2 = LEFT(@DB2,CHARINDEX('.',@DB2)-1)
if not exists (select * from master.dbo.sysservers where srvname = @SvrName2)
begin
print 'There is no linked server named '+@SvrName2+' Found. Precedure Terminates.'
return 
end
set @DBName2 = RIGHT(@DB2,LEN(@DB2)-CHARINDEX('.',@DB2))
end
else
set @DBName2 = @DB2
exec ('declare @Name sysname select @Name=name from ['+@SvrName2+'].master.dbo.sysdatabases where name = '''+@DBName2+'''')
if @@rowcount = 0
begin
print 'There is no database named '+@DB2+' Found. Precedure Terminates.'
return 
end

IF @DB1=@DB2
BEGIN
PRINT 'Both databases should be different. Precedure Terminates.'
   RETURN
END  

--End of validation
  
create Table #Procedures 
(      
 DBName sysname NOT NULL,       
 UserName sysname not null,       
 ProcName sysname NOT NULL,       
 Type varchar(2) NOT NULL,
 ObjID  int NOT NULL,   
 ObjID2 int NULL,        
 ProcID int Identity(1,1) NOT NULL      
)


Create Table  #ProcText 
(      
 ProcID int NOT NULL,      
 ColID int NOT NULL,      
 PText nvarchar(4000) NULL      
)      
      
Create Table #ProcLineText 
(      
 ProcID int NOT NULL,  
 LineID int NOT NULL,       
 LineText nvarchar(1000) NULL      
)      
    
Create Table #TableColumns 
(    
TABLE_CATALOG sysname NOT NULL,    
TABLE_SCHEMA sysname NOT NULL,    
TABLE_NAME sysname NOT NULL,    
COLUMN_NAME sysname NOT NULL,    
ORDINAL_POSITION smallint NOT NULL,    
COLUMN_DEFAULT nvarchar(2000) NULL,    
IS_NULLABLE bit NOT NULL,    
DATA_TYPE sysname NOT NULL,    
CHARACTER_MAXIMUM_LENGTH int NULL,    
CHARACTER_OCTET_LENGTH int NULL,    
NUMERIC_PRECISION tinyint NULL,    
NUMERIC_PRECISION_RADIX smallint NULL,    
NUMERIC_SCALE int NULL,     
DATETIME_PRECISION smallint NULL,
IS_COMPUTED bit NOT NULL,
IS_IDENTITY bit NOT NULL,
IDENTITY_SEED int NULL,
IDENTITY_INCR int NULL,
IS_FORREPL bit NOT NULL,
IS_ROWGUID bit NOT NULL, 
IS_DEFAULT bit NOT NULL,
IS_MAXIMUM bit NOT NULL,
IS_OCTET bit NOT NULL,    
IS_PRECISION bit NOT NULL,    
IS_RADIX bit NOT NULL,    
IS_SCALE bit NOT NULL,     
IS_DATETIME bit NOT NULL

)    
    
----------------------------------------------------------------------------------------    
--      Part I    
----------------------------------------------------------------------------------------  

-- Get the tables with column data       
set @SQL = 'Insert into  #TableColumns 
SELECT '''+@DB1 +''',    
usr.name, obj.name,    
Col.name,    
col.colid,    
com.text,    
col.isnullable,    
spt_dtp.LOCAL_TYPE_NAME,    
convert(int, OdbcPrec(col.xtype, col.length, col.xprec)  + spt_dtp.charbin),    
convert(int, spt_dtp.charbin + 
   case when spt_dtp.LOCAL_TYPE_NAME in (''nchar'', ''nvarchar'', ''ntext'')
 then  2*OdbcPrec(col.xtype, col.length, col.xprec) 
 else  OdbcPrec(col.xtype, col.length, col.xprec) 
   end),    
nullif(col.xprec, 0),    
spt_dtp.RADIX,    
col.scale,    
spt_dtp.SQL_DATETIME_SUB,
col.iscomputed,
col.colstat,
NULL,
NULL,
0, 
0,
0, 
0,
0, 
0,
0, 
0,
0
from ['+@SvrName1+'].['+@DBName1+'].dbo.sysobjects obj,
['+@SvrName1+'].master.dbo.spt_datatype_info spt_dtp,
['+@SvrName1+'].['+@DBName1 +'].dbo.systypes typ,
['+@SvrName1+'].['+@DBName1 +'].dbo.sysusers usr,
['+@SvrName1+'].['+@DBName1 +'].dbo.syscolumns col     
LEFT OUTER JOIN 
     ['+@SvrName1+'].['+@DBName1 +'].dbo.syscomments com on col.cdefault = com.id
AND com.colid = 1
WHERE
obj.id = col.id
     AND obj.uid=usr.uid 
AND typ.xtype = spt_dtp.ss_dtype
AND (spt_dtp.ODBCVer is null or spt_dtp.ODBCVer = 2)
AND obj.xtype in (''U'', ''V'')
AND col.xusertype = typ.xusertype
AND (spt_dtp.AUTO_INCREMENT is null or spt_dtp.AUTO_INCREMENT = 0)'
Execute (@SQL)    

set @SQL = 'Insert into  #TableColumns 
SELECT '''+@DB2 +''',    
usr.name, obj.name,    
Col.name,    
col.colid,    
com.text,    
col.isnullable,    
spt_dtp.LOCAL_TYPE_NAME,    
convert(int, OdbcPrec(col.xtype, col.length, col.xprec)  + spt_dtp.charbin),    
convert(int, spt_dtp.charbin + 
   case when spt_dtp.LOCAL_TYPE_NAME in (''nchar'', ''nvarchar'', ''ntext'')
 then  2*OdbcPrec(col.xtype, col.length, col.xprec) 
 else  OdbcPrec(col.xtype, col.length, col.xprec) 
   end),    
nullif(col.xprec, 0),    
spt_dtp.RADIX,    
col.scale,    
spt_dtp.SQL_DATETIME_SUB,
col.iscomputed,
col.colstat,
NULL,
NULL,
0, 
0,
0, 
0,
0, 
0,
0, 
0,
0
from ['+@SvrName2+'].['+@DBName2 +'].dbo.sysobjects obj,
['+@SvrName2+'].master.dbo.spt_datatype_info spt_dtp,
['+@SvrName2+'].['+@DBName2 +'].dbo.systypes typ,
['+@SvrName2+'].['+@DBName2 +'].dbo.sysusers usr,
['+@SvrName2+'].['+@DBName2 +'].dbo.syscolumns col     
LEFT OUTER JOIN 
     ['+@SvrName2+'].['+@DBName2 +'].dbo.syscomments com on col.cdefault = com.id
AND com.colid = 1
WHERE
obj.id = col.id
     AND obj.uid=usr.uid 
AND typ.xtype = spt_dtp.ss_dtype
AND (spt_dtp.ODBCVer is null or spt_dtp.ODBCVer = 2)
AND obj.xtype in (''U'', ''V'')
AND col.xusertype = typ.xusertype
AND (spt_dtp.AUTO_INCREMENT is null or spt_dtp.AUTO_INCREMENT = 0)' 

Execute (@SQL)    
SET @sql ='UPDATE #TableColumns SET IDENTITY_SEED =A.seed, IDENTITY_INCR = Incr 
From
(Select usr.name as table_Schema, obj.name as table_name, 
Seed =ident_seed(''['+@DBName2+'].''+usr.Name+''.''+obj.name),
Incr =ident_incr(''['+@DBName2+'].''+usr.name+''.''+obj.name) 
From [' + @SvrName2 + '].['+@DBName2+'].dbo.sysobjects obj,
[' + @SvrName2 + '].['+@DBName2+'].dbo.sysusers usr
WHERE obj.uid = usr.uid and 
ident_seed(''['+@DBName2+'].''+usr.Name+''.''+obj.name) is not NULL) A 
WHERE A.table_Schema=#TableColumns.Table_Schema and 
A.table_name = #TableColumns.Table_Name and 
#TableColumns.IS_IDENTITY & 1 = 1 and
#TableColumns.Table_catalog ='''+@DB2+''''  

Execute (@SQL)

SET @sql ='UPDATE #TableColumns SET IDENTITY_SEED =A.seed, IDENTITY_INCR = A.Incr 
From
(Select table_Schema=usr.name, table_name=obj.name, 
Seed =ident_seed(''['+@DBName1+'].''+usr.Name+''.''+obj.name),
Incr =ident_incr(''['+@DBName1+'].''+usr.name+''.''+obj.name) 
From [' + @SvrName1 + '].['+@DBName1+'].dbo.sysobjects obj,
[' + @SvrName1 + '].['+@DBName1+'].dbo.sysusers usr
WHERE obj.uid = usr.uid and 
ident_seed(''['+@DBName1+'].''+usr.Name+''.''+obj.name) is NOT NULL) A 
WHERE A.table_Schema= #TableColumns.Table_Schema and 
 A.table_name  = #TableColumns.Table_Name and 
 #TableColumns.IS_IDENTITY & 1 = 1 and
 #TableColumns.Table_Catalog ='''+@DB1+''''  
Execute (@SQL)

Update #TableColumns SET IS_DEFAULT =1 Where COLUMN_DEFAULT IS NOT NULL
Update #TableColumns SET IS_OCTET = 1 Where CHARACTER_OCTET_LENGTH IS NOT NULL
Update #TableColumns SET IS_RADIX = 1 Where NUMERIC_PRECISION_RADIX IS NOT NULL
Update #TableColumns SET IS_MAXIMUM = 1 Where CHARACTER_MAXIMUM_LENGTH IS NOT NULL
Update #TableColumns SET IS_PRECISION = 1 Where NUMERIC_PRECISION IS NOT NULL
Update #TableColumns SET IS_SCALE = 1 Where NUMERIC_SCALE IS NOT NULL
Update #TableColumns SET IS_DATETIME = 1 Where DATETIME_PRECISION IS NOT NULL

Update #TableColumns SET COLUMN_DEFAULT ='' WHERE COLUMN_DEFAULT IS NULL
Update #TableColumns SET CHARACTER_MAXIMUM_LENGTH=0 WHERE CHARACTER_MAXIMUM_LENGTH is NULL
Update #TableColumns SET CHARACTER_OCTET_LENGTH=0 WHERE CHARACTER_OCTET_LENGTH IS NULL    
Update #TableColumns SET NUMERIC_PRECISION =0 WHERE NUMERIC_PRECISION IS NULL    
Update #TableColumns SET NUMERIC_PRECISION_RADIX = 0 WHERE NUMERIC_PRECISION_RADIX IS NULL
Update #TableColumns SET NUMERIC_SCALE = 0 WHERE NUMERIC_SCALE is NULL     
Update #TableColumns SET DATETIME_PRECISION=0 WHERE DATETIME_PRECISION is NULL


    
PRINT 'Tables & Views that exists only in '+@DB1    
print '-----------------------------------'+Replicate('-', len(@DB1))    
Select Distinct Table_Schema +'.'+Table_Name
From #TableColumns 
Where Table_Catalog=@DB1 and Table_Schema+Table_Name not in (    
    Select Table_Schema+Table_Name from #TableColumns
    Where Table_Catalog =@DB2)    
if @@RowCount =0    
    Print '(none)'    
    
Print ''    
    
Print 'Tables & Views that exists only in '+@DB2    
print '-----------------------------------'+replicate('-', len(@DB2))    
Select Distinct Table_Schema+'.'+Table_Name
From #TableColumns 
Where Table_Catalog=@DB2 and Table_Schema+Table_Name not in (    
    Select Table_Schema+Table_Name from #TableColumns
    Where Table_Catalog =@DB1)    
if @@RowCount =0    
Print '(none)'    
    
Print ''    
    
  
--Now check for additional Columns    
Print 'Columns that are missing on the table/View'    
Print '------------------------------------------'    
     
Select Distinct [Missing in Database] =    
Case A.Table_Catalog    
    WHEN @DB1 THEN @DB2    
    ELSE @DB1    
    END, 
[Missing Column]=A.Table_Catalog+'.'+     
    A.Table_Schema+'.'+A.Table_Name+'  -  '+ A.Column_Name,    
 'Default'= 
CASE A.IS_DEFAULT
WHEN 1 THEN A.Column_Default 
ELSE NULL
END,    
 'Allow Null' =
CASE A.Is_Nullable 
WHEN 1 THEN 'Yes'
ELSE 'NO'
END,    
 A.Data_Type [Data type],    
'Maximum Length'=
CASE A.IS_MAXIMUM
WHEN 1 THEN A.Character_Maximum_Length    
ELSE NULL
END,
 'Numeric Precision'=
CASE A.IS_PRECISION
WHEN 1 THEN A.Numeric_Precision
ELSE NULL
END,
 'Numeric Precision Radix'=
CASE A.IS_RADIX
WHEN 1 THEN A.Numeric_Precision_Radix
ELSE NULL
END,
'Numeric Scale'=
CASE A.IS_SCALE
WHEN 1 THEN A.Numeric_Scale
ELSE NULL
END,
 'Date Time Precision'=
case A.IS_DateTime
WHEN 1 THEN A.Datetime_Precision     
ELSE NULL
END,
'Identity ?'=
CASE A.IS_IDENTITY
WHEN 1 THEN 'Yes'
ELSE 'No'
END ,
Seed = 
Case A.IS_IDENTITY 
WHEN 1 THEN A.IDENTITY_SEED
ELSE NULL
END,
Increment =
Case A.IS_IDENTITY 
WHEN 1 THEN A.IDENTITY_INCR
ELSE NULL
END
From (#TableColumns  A     
LEFT OUTER JOIN #TableColumns B On    
A.Table_Schema= B.Table_Schema and     
A.Column_Name = B.Column_Name  and     
A.Table_Name = B.Table_Name and A.Table_Catalog<>B.Table_Catalog)    
INNER JOIN #TableColumns C On A.Table_Schema= C.Table_Schema and    
 A.Table_Name = C.Table_Name and    
 A.Table_Catalog<>C.Table_Catalog    
Where B.Table_Name is NULL      
Order By A.Table_Catalog+'.'+A.Table_Schema+'.'+ A.Table_Name+'  -  '+ A.Column_Name    
IF @@ROWCOUNT =0     
   Print '(none)'    
--Column is there but length / precision is different    
Print 'Different Columns Definitions'    
Print '-----------------------------'    
    
Select A.Table_Name, A.Column_Name,     
A.Table_Catalog+'.'+ A.Table_Schema as [Data Base],
'Default'=
CASE A.IS_DEFAULT
WHEN 1 THEN A.Column_Default
ELSE NULL
END,
 'Allow Null' =
CASE A.Is_Nullable 
WHEN 1 THEN 'Yes'
ELSE 'NO'
END,    
 A.Data_Type [Data type],  
'Maximum Length'=
CASE A.IS_MAXIMUM
WHEN 1 THEN A.Character_Maximum_Length    
ELSE NULL
END,
 'Numeric Precision'=
CASE A.IS_PRECISION
WHEN 1 THEN A.Numeric_Precision
ELSE NULL
END,
 'Numeric Precision Radix'=
CASE A.IS_RADIX
WHEN 1 THEN A.Numeric_Precision_Radix
ELSE NULL
END,
'Numeric Scale'=
CASE A.IS_SCALE
WHEN 1 THEN A.Numeric_Scale
ELSE NULL
END,
 'Date Time Precision'=
case A.IS_DateTime
WHEN 1 THEN A.Datetime_Precision     
ELSE NULL
END,
'Identity ?'=
CASE A.IS_IDENTITY
WHEN 1 THEN 'Yes'
ELSE 'No'
END ,
Seed =
Case A.IS_IDENTITY 
WHEN 1 THEN A.IDENTITY_SEED
ELSE NULL
END,
increment =
Case A.IS_IDENTITY 
WHEN 1 THEN A.IDENTITY_INCR
ELSE NULL
END
From #TableColumns A     
INNER JOIN #TableColumns B On    
 A.Table_Catalog<>B.Table_Catalog and    
 A.Table_Schema= B.Table_Schema and     
 A.Table_Name = B.Table_Name and     
 A.Column_Name = B.Column_Name and    
 (A.Column_Default<>B.Column_Default or    
  A.Is_Nullable<>B.Is_Nullable or    
  A.Data_Type<>B.Data_Type or    
  A.Character_Maximum_Length<>B.Character_Maximum_Length or    
  A.Numeric_Precision<>B.Numeric_Precision or    
  A.Numeric_Scale<>B.Numeric_Scale or    
  A.Datetime_Precision<>B.Datetime_Precision or
A.IS_IDENTITY<>B.IS_IDENTITY or
A.IDENTITY_SEED<>B.IDENTITY_SEED or
A.IDENTITY_INCR<>B.IDENTITY_INCR or
A.IS_DEFAULT <>B.IS_DEFAULT  or
A.IS_MAXIMUM <>B.IS_MAXIMUM or
A.IS_OCTET <>B.IS_OCTET or
A.IS_PRECISION <>B.IS_PRECISION or
A.IS_RADIX <>B.IS_RADIX or
A.IS_SCALE <>B.IS_SCALE or
A.IS_DATETIME<>B.IS_DATETIME)    
Order By A.Table_Name, A.Column_Name,     
 A.Table_Catalog+'.'+A.Table_Schema    
IF @@ROWCOUNT =0     
   Print '(none)'    
  
Print ''
Print ''
  
----------------------------------------------------------------------------------------    
--      Part II:     
----------------------------------------------------------------------------------------  
-- Get the other objects found only in @DB1    
Set @SQL = 'Insert into #Procedures (DBName, UserName, ProcName, Type, ObjID)  
Select ''' + @DB1 +''', A.Name,  B.Name, B.Type, B.ID 
from ['+@SvrName1+'].['+@DBName1+'].dbo.Sysusers A, 
['+@SvrName1+'].['+@DBName1+'].dbo.SysObjects B 
Where A.uid = B.uid and 
B.Category = 0 and B.Type in (''P'', ''V'', ''Tr'', ''FN'')      
and A.Name+B.Name NOT IN (Select A.Name+B.Name 
From ['+@SvrName2+'].['+@DBName2+'].dbo.Sysusers A, 
['++@SvrName2+'].['+@DBName2+'].dbo.SysObjects B Where A.uid = B.uid)'      
      
Execute(@SQL)      
     
-- Get the objects found only in @DB1    
Set @SQL = 'Insert into #Procedures (DBName, UserName, ProcName, Type, ObjID)  
Select ''' + @DB2 +''', A.Name,  B.Name, B.Type, B.ID 
from ['+@SvrName2+'].['+@DBName2+'].dbo.Sysusers A, 
['+@SvrName2+'].['+@DBName2+'].dbo.SysObjects B 
Where A.uid = B.uid and 
B.Category = 0 and B.Type in (''P'', ''V'', ''Tr'', ''FN'')      
and A.Name+B.Name NOT IN (Select A.Name+B.Name 
From ['+@SvrName1+'].['+@DBName1+'].dbo.Sysusers A, 
['+@SvrName1+'].['+@DBName1+'].dbo.SysObjects B 
Where A.uid = B.uid)'      
Execute(@SQL)      
   
-- Get the existing Objects  
Set @SQL = 'Insert into #Procedures (DBName, UserName, ProcName, Type, ObjID, ObjID2)  
Select ''' + @DB1 +''', A.Name,  B.Name, B.type, B.ID, D.ID 
from ['+@SvrName1+'].['+@DBName1 +'].dbo.Sysusers A,
     ['+@SvrName1+'].['+@DBName1 +'].dbo.SysObjects B, 
     ['+@SvrName2+'].['+@DBName2 +'].dbo.SysUsers C, 
     ['+@SvrName2+'].['+@DBName2+'].dbo.SysObjects D   
Where A.uid = B.uid and B.Category = 0 and B.Type in (''P'', ''V'', ''Tr'', ''FN'')  
      and A.Name = C.Name and B.Name=D.Name and C.uid = D.uid'      
Execute(@SQL)      
  
Set @SQL = 'Insert into #Procedures (DBName, UserName, ProcName, Type, ObjID, ObjID2)  
Select ''' + @DB2 +''', A.Name,  B.Name, B.type, B.ID, D.ID 
from ['+@SvrName2+'].['+@DBName2 +'].dbo.Sysusers A, 
     ['+@SvrName2+'].['+@DBName2 +'].dbo.SysObjects B, 
     ['+@SvrName1+'].['+@DBName1 +'].dbo.SysUsers C, 
     ['+@SvrName1+'].['+@DBName1+'].dbo.SysObjects D   
Where A.uid = B.uid and B.Category = 0 and B.Type in (''P'', ''V'', ''Tr'', ''FN'')  
 and A.Name = C.Name and B.Name=D.Name and C.uid = D.uid'      
Execute(@SQL)     
   
--Get the Text of the objects    
SET @SQL ='Insert into #ProcText 
Select P.ProcID, C.COLID, C.Text 
From #Procedures P, ['+@SvrName1+'].['+@DBName1+'].dbo.SysComments C 
Where P.objID =c.id and P.DBName ='''+@DB1+''''      
Execute(@SQL)      
      
SET @SQL ='Insert into #ProcText       
Select P.ProcID, C.ColID, C.Text       
From #Procedures P, ['+@SvrName2+'].['+@DBName2+'].dbo.SysComments C       
Where P.objID =C.id and P.DBName ='''+@DB2+''''      
Execute(@SQL)      
  
DECLARE ms_crs_syscom  CURSOR LOCAL FORWARD_ONLY  
        FOR Select P.ProcID, D.PText from #Procedures P, #ProcText D  
 WHERE P.ProcID = D.PRocID Order By P.DBName, P.ProcID, D.ColID      
        FOR READ ONLY      
      
SELECT @LFCR = 2      
SELECT @LineId = 1      
          
OPEN ms_crs_syscom      
SET @OldProcID = -1      
FETCH NEXT FROM ms_crs_syscom into  @ProcID, @SyscomText      
      
WHILE @@fetch_status = 0      
BEGIN      
      
    SELECT  @BasePos    = 1      
    SELECT  @CurrentPos = 1      
    SELECT  @TextLength = LEN(@SyscomText)  
  
    IF @ProcID <>@OldProcID       
    BEGIN      
 SET @LineID = 1       
SET @OldProcID = @ProcID      
    END      
    WHILE @CurrentPos  != 0      
    BEGIN      
        --Looking for end of line followed by carriage return      
        SELECT @CurrentPos =   CHARINDEX(char(13)+char(10), @SyscomText, @BasePos)      
      
        --If carriage return found      
        IF @CurrentPos != 0      
        BEGIN      
            /*If new value for @Lines length will be > then the      
            **set length then insert current contents of @line      
            **and proceed.      
  */      
            While (isnull(LEN(@Line),0) + @BlankSpaceAdded + @CurrentPos-@BasePos + @LFCR) > @DefinedLength      
            BEGIN      
   SELECT @AddOnLen = @DefinedLength-(isnull(LEN(@Line),0) + @BlankSpaceAdded)      
                INSERT #ProcLineText VALUES      
                ( @ProcID, @LineId,      
                  isnull(@Line, N'') + isnull(SUBSTRING(@SyscomText, @BasePos, @AddOnLen), N''))      
                SELECT @Line = NULL, @LineId = @LineId + 1,      
                       @BasePos = @BasePos + @AddOnLen, @BlankSpaceAdded = 0      
            END      
            SELECT @Line    = isnull(@Line, N'') + isnull(SUBSTRING(@SyscomText, @BasePos, @CurrentPos-@BasePos + @LFCR), N'')      
            SELECT @BasePos = @CurrentPos+2      
            INSERT #ProcLineText VALUES( @ProcID, @LineId, @Line )      
            SELECT @LineId = @LineId + 1      
            SELECT @Line = NULL      
        END      
        ELSE      
        --else carriage return not found      
        BEGIN      
            IF @BasePos <= @TextLength      
            BEGIN      
                /*If new value for @Lines length will be > then the      
                **defined length      
                */      
                While (isnull(LEN(@Line),0) + @BlankSpaceAdded + @TextLength-@BasePos+1 ) > @DefinedLength      
                BEGIN      
                    SELECT @AddOnLen = @DefinedLength - (isnull(LEN(@Line),0) + @BlankSpaceAdded)      
                    INSERT #ProcLineText VALUES      
                    ( @ProcID, @LineId,      
                      isnull(@Line, N'') + isnull(SUBSTRING(@SyscomText, @BasePos, @AddOnLen), N''))      
                    SELECT @Line = NULL, @LineId = @LineId + 1,      
                        @BasePos = @BasePos + @AddOnLen, @BlankSpaceAdded = 0      
                END      
                SELECT @Line = isnull(@Line, N'') + isnull(SUBSTRING(@SyscomText, @BasePos, @TextLength-@BasePos+1 ), N'')      
                if LEN(@Line) < @DefinedLength and charindex(' ', @SyscomText, @TextLength+1 ) > 0      
                BEGIN      
                    SELECT @Line = @Line + ' ', @BlankSpaceAdded = 1      
                END      
            END      
        END      
    END      
      
 FETCH NEXT FROM ms_crs_syscom into @ProcID, @SyscomText      
END      
      
IF @Line is NOT NULL      
    INSERT #ProcLineText VALUES( @ProcId, @LineId, @Line )      
      
      
CLOSE  ms_crs_syscom      
IF (@ShowDifferentOnly=0)  
BEGIN  
Print 'Procedures/Triggers Found Only in ' +@DB1      
Print '----------------------------------'+Replicate('-', LEN(@DB1))      
     
Select L.LineText as 'Text'      
From #ProcLineText L, #Procedures P       
Where P.DBName =@DB1 and P.ObjID2 is NULL and L.ProcID = P.ProcID and
P.Type<>'V'
Order By ObjID, LineID      
IF @@RowCount=0      
 Print '(None)'      
      
Print ' '      
      
Print 'Procedures/Triggers Found Only in ' +@DB2      
Print '----------------------------------'+Replicate('-', LEN(@DB2))      
      
Select L.LineText as 'Text'      
From #ProcLineText L, #Procedures P  
Where P.DBName =@DB2 and P.ObjID2 is NULL and P.ProcId = L.PRocID and
P.Type<>'V'      
Order By ObjID, LineID      
IF @@RowCount=0      
 Print '(None)'      
      
Print ' '      
END  
ELSE
BEGIN  
Print 'Procedures/Triggers Found Only in ' +@DB1      
Print '----------------------------------'+Replicate('-', LEN(@DB1))      
     
Select UserName+'.'+ ProcName
From #Procedures        
Where DBName =@DB1 and ObjID2 is NULL and Type<>'V'
IF @@RowCount=0      
 Print '(None)'      
      
Print ' '      
      
Print 'Procedures/Triggers  Found Only in ' +@DB2      
Print '-----------------------------------'+Replicate('-', LEN(@DB2))      
      
Select UserName+'.'+ ProcName
From #Procedures        
Where DBName =@DB2 and ObjID2 is NULL and Type<>'V'
IF @@RowCount=0      
 Print '(None)'      
      
Print ' '      
END  
      
Print ' '      
--This part shows only the different lines     
IF (@ShowDifferentOnly=1)  
BEGIN  

Print 'Views, Stored Procedures and Triggers with different Code (Lines Only)'      
Print '---------------------------------------------------------------------'      
Select P.UserName+'.'+P.ProcName [Procedure Name],  P.DBName [Database Name], 
A.LineID [Line ID], A.LineText [Text]      
From #ProcLineText A, #ProcLineText B, #Procedures P, #Procedures Q       
Where P.ProcName = Q.ProcName and P.UserName = Q.UserName and 
 P.ProcID=A.ProcID and Q.ProcID = B.ProcID and P.ProcID<>Q.ProcID and
 A.LineID = B.LineID and   
 P.ObjID2 =Q.ObjID and Q.ObjID2 =P.ObjID and    
 A.LineText <>B.LineText       
Order By P.UserName+'.'+P.ProcName, A.LineID, P.DBName

IF @@RowCount=0      
 Print '(None)'      
END     
ELSE
BEGIN      
 Print ''      
 Print ''      
 --This part shows all lines of the object (both databses) where there is a differnece    
 Print 'Views, Stored Procedures and Triggers with different Code (Complete SQL Statements)'      
 Print '-----------------------------------------------------------------------------------'      
 Print @DB1      
 Print Replicate('-', Len(@DB1))      
       
 Select C.LineText [Text]      
 from #ProcLineText C,       
 (Select P.ProcID 
From #ProcLineText A, #ProcLineText B, #Procedures P, #Procedures Q       
Where P.ProcName = Q.ProcName and P.UserName = Q.UserName and 
 P.ProcID=A.ProcID and Q.ProcID = B.ProcID and P.ProcID<>Q.ProcID and
 A.LineID = B.LineID and P.DBName =@DB1 and Q.DBName = @DB2  and
 P.ObjID2 =Q.ObjID and Q.ObjID2 =P.ObjID and    
 A.LineText <>B.LineText) D  
 Where C.ProcID =D.ProcID   
 Order By C.ProcID, C.LineId
 
 IF @@RowCount=0      
 Print '(None)'      
 Print ''
      
 Print @DB2      
 Print Replicate('-', Len(@DB2))      
       
 Select C.LineText [Text]      
 from #ProcLineText C,       
 (Select P.ProcID
From #ProcLineText A, #ProcLineText B, #Procedures P, #Procedures Q       
Where P.ProcName = Q.ProcName and P.UserName = Q.UserName and 
 P.ProcID=A.ProcID and Q.ProcID = B.ProcID and P.ProcID<>Q.ProcID and
 A.LineID = B.LineID and P.DBName =@DB2 and Q.DBName = @DB1  and
 P.ObjID2 =Q.ObjID and Q.ObjID2 =P.ObjID and    
 A.LineText <>B.LineText) D  
 Where C.ProcID =D.ProcID   
 Order By C.ProcID, C.LineId      
       
 IF @@RowCount=0      
  Print '(None)'      
END    
      
Print '-------------------------- End ---------------------------------------'      
      
Deallocate ms_crs_syscom        
Drop Table #ProcLineText      
Drop Table #ProcText      
Drop table #Procedures      
Drop table #TableColumns
Set nocount off

Rate

You rated this post out of 5. Change rating

Share

Share

Rate

You rated this post out of 5. Change rating