【问题标题】:Get the SHA-512 of any SQL query获取任何 SQL 查询的 SHA-512
【发布时间】:2018-06-07 01:07:13
【问题描述】:

比较两个文本文件的常见做法是使用 SHA-512 [或任何其他相关的 SHA 算法]。如果两个 SHA 结果不相同,则文件不完全相同。

我想对两个 SQL 查询做同样的事情。我只想知道查询是否使用 SHA-512 [或 sha-256 也可以] 给出 100% 相同的结果?

有可能做到吗?我正在使用 SQL Server...

【问题讨论】:

  • 要比较SQL查询文本还是查询结果?无论如何,不​​同的查询可能会在特定条件下返回相同的结果(你会得到很多误报)
  • 大致上,您可以在查询底部添加FOR XML AUTO 并在结果中添加HASHBYTES。但是,SQL Server 2014 及更早版本的哈希值不能超过 8000 字节,所以如果您使用的是这些版本,就会出现问题。
  • 为什么不在你的两个查询之间使用EXCEPT 看看是否有任何问题?这样您就不必担心排序或任何其他可能在哈希或校验和中被拾取并导致您的检查失败的时髦事物。
  • 我认为这样做会使您的生活变得不必要地复杂化。正如@JNevill 所说,你为什么不使用EXCEPT 子句?
  • I just want to know if the queries gives 100% identical result Counterexample

标签: sql sql-server sha sha512


【解决方案1】:

只是为了帮助...

据了解,两个查询以相同的顺序返回相同的列。

你必须这样做:

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

如果返回 0,则两个查询返回相同

出于测试目的:

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

更改一些内部查询,看看有什么变化

【讨论】:

    【解决方案2】:

    下面是一些使用 2 种方法的示例 SQL。

    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);
    

    在此示例中,两个动态查询都返回“true”。

    但请注意,仅仅因为结果集相同,并不意味着使用的标准是等效的。
    他们目前返回相同的结果可能只是运气不好。
    (只需取消注释 monkeywrench 记录以从两者中获取错误)

    另外,关于 FOR XML。当其中一个 ORDER BY 不同时,那么生成的 XML 和 HASH 也会不同。

    虽然使用 EXCEPT,但您只能在末尾添加 ORDER BY,因为它会对组合的结果集进行排序。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-01
      • 2018-03-12
      • 1970-01-01
      相关资源
      最近更新 更多