Вот пример SQL, который использует 2 метода.
- ДЛЯ XML & ХАШБИТЫ
- ИСКЛЮЧИТЬ
IF OBJECT_ID('tempdb..#tmpTest') IS NOT NULL DROP TABLE #tmpTest;
CREATE TABLE #tmpTest (
id int identity(1,1) primary key,
col1 decimal(10,2),
col2 varchar(30)
);
insert into #tmpTest (col1, col2) values
(1,'val1'),
(null,'val2'),
(3,null),
(4,'val4')
-- ,(5,'monkeywrench')
;
declare @SQL1 VARCHAR(1000);
declare @SQL2 VARCHAR(1000);
declare @SQLHASH VARCHAR(3000);
declare @SQLEXCEPT VARCHAR(5000);
set @SQL1 = 'select col1, col2
from #tmpTest
where (col1 is null or col1 between 1 and 4)
';
set @SQL2 = 'select col1, col2
from #tmpTest
where (col2 is null or col2 is not null)
';
set @SQLHASH = 'select
IIF(LEN(query1.x) = LEN(query2.x) AND HASHBYTES(''SHA2_512'', query1.x) = HASHBYTES(''SHA2_512'', query2.x),''true'',''false'') as SameHash
from (
'+ @SQL1 +'
order by 1, 2
for xml auto
) query1(x)
cross join (
'+ @SQL2 +'
order by 1, 2
for xml auto
) query2(x)';
--select @SQLHASH as SQLHASH;
execute(@SQLHASH);
set @SQLEXCEPT = 'select
IIF(count(*) = 0,''true'',''false'') as SameRecords
from (
select * from
(
'+ @SQL1 +'
except
'+ @SQL2 +'
) as q1exceptq2
union all
select * from (
'+ @SQL2 +'
except
'+ @SQL1 +'
) as q2exceptq1
) q';
--select @SQLEXCEPT as SQLEXCEPT;
execute(@SQLEXCEPT);
В этом примере оба динамических запроса возвращают значение «true».
Но учтите, что тот факт, что наборы результатов совпадают, не означает, что используемые критерии эквивалентны.
Это может быть просто плохоповезло, что они в настоящее время возвращают одинаковые результаты.
(просто раскомментируйте запись с ключом-ключом, чтобы получить ложное от обоих)
Кроме того, о FOR XML.Если один из ORDER BY отличается, то результирующий XML и HASH также будут отличаться.
Хотя с ИСКЛЮЧЕНИЕМ вы можете добавить только ORDER BY в конце, потому что он сортирует объединенный набор результатов.