Get the SHA-512 of any SQL query

百般思念 提交于 2019-12-11 06:55:17

问题


A common practice to compare two text file is to use the SHA-512 [or any other realted SHA algo]. If two SHA results are not the same then the files are not exactely the same.

I would like to do the same with two SQL queries. I just want to know if the queries gives 100% identical result or not with a SHA-512 [or sha-256 would be OK as well]?

Is that possible to perform that? I am using SQL Server...


回答1:


Just to help...

It's understood that both queries return the same columns in the same order.

You must do:

SELECT COUNT(*) FROM (
  ([YOUR_QUERY_A]
   EXCEPT
   [YOUR_QUERY_B]) -- A_B
  UNION ALL
  ([YOUR_QUERY_B]
   EXCEPT
   [YOUR_QUERY_A]) -- B_A
  ) EX

If returns 0, both queries return the same

For test purposes:

SELECT COUNT(*) FROM (
  (select 1 a
   EXCEPT
   select 1)
  UNION ALL
  (select 1
   EXCEPT
   select 1)
  ) EX

Change some inner query and look what changes




回答2:


Here's some example SQL that uses 2 methods.

  1. FOR XML & HASHBYTES
  2. EXCEPT
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);

In this example, both dynamic queries return 'true'.

But do note that just because the result sets are the same, doesn't mean that the criteria used are equivalent.
It might just be bad luck that they are currently returning the same results.
(just uncomment the monkeywrench record to get false from both)

Also, about the FOR XML. When one of the ORDER BY is different, then the resulting XML and HASH will also be different.

While with an EXCEPT you can only add an ORDER BY at the end, because it sorts the combined resultset.



来源:https://stackoverflow.com/questions/50724104/get-the-sha-512-of-any-sql-query

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!