/*
Compare master table data on 2 servers (
1. Change server name
2. Set RaceDate (@racedate) with the >, < ,= >= operator
before you run)
--KNOWN ISSUES
1. Tables need PKs
*/
SET NOCOUNT ON
--Destination Server Details
DECLARE @destServ nvarchar(40)='[sql\inst23]' --required -- If local instance, leave the string empty
DECLARE @destdb nvarchar(40)='DBName' --required
DECLARE @destSchema nvarchar(40)='dbo' --required
DECLARE @destTable nvarchar(40)='TableName' --required
-- Source Server Details
DECLARE @SourServ nvarchar(40)='[sql\inst07]' --required
DECLARE @Sourdb nvarchar(40)='DBonRemoteServer' --required
DECLARE @SourSchema nvarchar(40)='dbo' --required
DECLARE @SourTable nvarchar(40)='TableName' --required -- TableName format 'MyTable'
DECLARE @WHERE nvarchar(400) = 'WHERE 1=1'
DECLARE @Clause nvarchar(400)= 'AND Id > 201808201500000' --Choose a Predicate to limit data --Start with AND . e.g: 'AND Date > ''20180801'' '
SELECT @WHERE = @WHERE + @Clause
DECLARE @randomtablesuffix nvarchar(5)
SELECT @randomtablesuffix= SUBSTRING(CAST(NEWID() as nvarchar(255)),1,5)
declare @v nvarchar(max), @sql nvarchar(max), @retval nvarchar(max) , @ParamDef nvarchar(400)
--GET Columns List as varchar Columns for HASHBYTES to compare
SELECT @sql='SELECT @vv= COALESCE(@vv,'''')+''CAST(ISNULL(''+ COLUMN_NAME + '',0) as VARCHAR(''+
CASE WHEN DATA_TYPE IN (''varchar'',''nvarchar'') THEN CAST(CHARACTER_MAXIMUM_LENGTH as varchar(5)) ELSE ''60 '' END +'')) + ''
from '+ @destdb + '.INFORMATION_SCHEMA.COLUMNS where TABLE_NAME='+ QUOTENAME(@destTable,'''') + ''
SET @ParamDef = N'@vv nvarchar(max) OUTPUT'
EXEC sp_executesql @sql, @ParamDef, @vv=@v OUTPUT;
SELECT @v= SUBSTRING(@v,0,LEN(@v))
--Keys to JOIN
DECLARE @pkeylistJoinOUT nvarchar(4000)=''
SET @sql='SELECT @pkeylistJoin = ISNULL(@pkeylistJoin,'''') + '' a.''+ QUOTENAME(COLUMN_NAME) + ''=b.''+ QUOTENAME(COLUMN_NAME) + '' AND''
FROM '+@destdb+'.[INFORMATION_SCHEMA].[KEY_COLUMN_USAGE]
WHERE TABLE_NAME='+ QUOTENAME(@destTable,'''') + ' ORDER BY ORDINAL_POSITION'
SET @ParamDef = N'@pkeylistJoin nvarchar(max) OUTPUT'
EXEC sp_executesql @sql, @ParamDef, @pkeylistJoin=@pkeylistJoinOUT OUTPUT;
SELECT @pkeylistJoinOUT = REPLACE(REPLACE(REVERSE( SUBSTRING(REVERSE(@pkeylistJoinOUT), CHARINDEX(']', REVERSE(@pkeylistJoinOUT)), LEN(@pkeylistJoinOUT)) ),']',''),'[','')
--Get Column List
DECLARE @ColumnListOut nvarchar(max)=''
SET @sql='SELECT @ColumnList=ISNULL(@ColumnList,'''') + COLUMN_NAME + '','' FROM '+@destdb +'.[INFORMATION_SCHEMA].[COLUMNS] WHERE TABLE_NAME='+QUOTENAME(@destTable,'''')+ ' ORDER BY ORDINAL_POSITION'
SET @ParamDef = N'@ColumnList nvarchar(max) OUTPUT'
EXEC sp_executesql @sql, @ParamDef, @ColumnList=@ColumnListOut OUTPUT;
SET @ColumnListOut=SUBSTRING(@ColumnListOut,0,LEN(@ColumnListOut))
--Now Compare
SELECT @sql='
SELECT a.* INTO ##_destissues'+@randomtablesuffix+' FROM (
SELECT HASHBYTES (''SHA2_512'','+ @v +')HashVal,'+ @ColumnListOut +' FROM '+@destServ+'.'+@destdb+'.'+@destSchema+'.'+@destTable + ' x WITH (NOLOCK) ' + @WHERE + '
)a
JOIN (
SELECT HASHBYTES (''SHA2_512'','+@v +')HashVal,'+ @ColumnListOut + ' FROM ' +@SourServ +'.'+ @Sourdb+ '.'+@SourSchema+'.'+ @SourTable +' y WITH (NOLOCK) ' + @WHERE + '
)
b ON '+@pkeylistJoinOUT + ' AND a.HashVal <> b.HashVal '
--print @sql
exec (@sql)
SELECT @sql='
SELECT b.* INTO ##_sourceissues'+@randomtablesuffix+ ' FROM (
SELECT HASHBYTES (''SHA2_512'','+ @v +')HashVal,'+ @ColumnListOut +' FROM '+@destServ+'.'+@destdb+'.'+@destSchema+'.'+@destTable + ' x WITH (NOLOCK) ' + @WHERE + '
)a
JOIN (
SELECT HASHBYTES (''SHA2_512'','+@v +')HashVal,'+ @ColumnListOut + ' FROM ' +@SourServ +'.'+ @Sourdb+ '.'+@SourSchema+'.'+ @SourTable +' y WITH (NOLOCK) ' + @WHERE + '
)
b ON '+@pkeylistJoinOUT + ' AND a.HashVal <> b.HashVal '
exec (@sql)
--Get Column List for Pivoting
DECLARE @ColumnListOutasVC nvarchar(max)=''
SET @sql='SELECT @ColumnList=ISNULL(@ColumnList,'''')+ ''CAST(''+ COLUMN_NAME + '' AS VARCHAR(200)) as ''+ COLUMN_NAME + '','' FROM ' + @destdb+'.[INFORMATION_SCHEMA].[COLUMNS] WHERE TABLE_NAME='+QUOTENAME(@desttable,'''')
SET @ParamDef = N'@ColumnList nvarchar(max) OUTPUT'
EXEC sp_executesql @sql, @ParamDef, @ColumnList=@ColumnListOutasVC OUTPUT;
SET @ColumnListOutasVC=SUBSTRING(@ColumnListOutasVC,0,LEN(@ColumnListOutasVC))
--Get PKs as VARCHAR Values
DECLARE @pkeylistJoinOUTVC nvarchar(4000)=''
SET @sql='SELECT @pkeylistJoin = ISNULL(@pkeylistJoin,'''') + ''CAST(''+COLUMN_NAME + '' as varchar(200)) as '' + COLUMN_NAME + ''1,'' FROM '+ @destdb+'.[INFORMATION_SCHEMA].[KEY_COLUMN_USAGE] WHERE TABLE_NAME='+QUOTENAME(@destTable,'''') + ' ORDER BY ORDINAL_POSITION'
SET @ParamDef = N'@pkeylistJoin nvarchar(max) OUTPUT'
EXEC sp_executesql @sql, @ParamDef, @pkeylistJoin=@pkeylistJoinOUTVC OUTPUT;
SET @pkeylistJoinOUTVC=SUBSTRING(@pkeylistJoinOUTVC,0,LEN(@pkeylistJoinOUTVC))
--SELECT @pkeylistJoinOUTVC
SET @sql='
select * INTO ##_destissuedetail'+@randomtablesuffix+ ' from(
select '+ @pkeylistJoinOUTVC + ', ' + @ColumnListOutasVC
+ '
from
##_destissues'+ @randomtablesuffix+ '
)c UNPIVOT
(
Vals for ColNames in ('+@ColumnListOut+')
) d'
EXEC( @sql)
SET @sql='
select * INTO ##_sourceissuedetail'+@randomtablesuffix+' from(
select '+ @pkeylistJoinOUTVC + ', ' + @ColumnListOutasVC
+ '
from
##_sourceissues'+ @randomtablesuffix+'
)c UNPIVOT
(
Vals for ColNames in ('+@ColumnListOut+')
) d'
EXEC( @sql)
SELECT 'Tables to look for data are ##_destissuedetail'+@randomtablesuffix +' and ##_sourceissuedetail ' +@randomtablesuffix
SET @sql='
SELECT * FROM ##_destissuedetail'+@randomtablesuffix+ '
EXCEPT
SELECT * FROM ##_sourceissuedetail' +@randomtablesuffix
EXEC (@sql)
Lo script (se fornito con i dettagli pertinenti) confronta 2 tabelle (ad esempio Clienti sul server1 con Clienti sul Server2).
Questo script sarà utile se stai confrontando una tabella con molte colonne ma fai fatica a trovare la colonna di mancata corrispondenza esatta.
Ho una tabella con 353 colonne e ho dovuto confrontarla con un'altra tabella e trovare i valori non corrispondenti e questo script ti aiuterà a individuare la tupla esatta.