从SQL Server和Oracle获取哈希值并进行比较?

时间:2012-01-10 21:03:31

标签: sql-server oracle hash

是否可以从两个数据库服务器生成哈希代码并进行比较?如何在SQL Server中编写以下伪SQL?特别是两个getHash函数,它们接受SQL Server和oracle中的多个数字/浮点列。

select s.PK
from sqltable s
    join openquery(oracleLinkedServer, 
      'select PK, getHash(Column1, floatColumn2, ..., floatColumnN) oracleHash 
       from oracleTable') o on o.PK = s.PK
where
    getHash(Column1, floatColumn2, ..., floatColumnN) <> oracleHash

4 个答案:

答案 0 :(得分:10)

在SQL Server中:

select upper(substring(sys.fn_sqlvarbasetostr(hashbytes('MD5','A')),3,32));

结果:

7FC56270E7A70FA81A5935B72EACBE29

在Oracle中:

select rawtohex(
    DBMS_CRYPTO.Hash (
        UTL_I18N.STRING_TO_RAW ('A', 'AL32UTF8'),
        2)
    ) from dual;

结果:

7FC56270E7A70FA81A5935B72EACBE29

确保您的字符串完全相同(区分大小写)。在这里我使用'A'作为一个简单的例子,但它可以是任何字符串。

如果通过转换为大字符串来避免数据类型差异,则应该能够在不同平台上生成相同的md5哈希。请注意,SQL Server在哈希前面添加了一个'0x'来表示十六进制表示,我用子字符串去掉了。

答案 1 :(得分:3)

在SQL Server中,您有hashbytes();在Oracle中,您有DBMS_CRYPTO.Hash()。你应该能够使用它们来计算双方的MD5哈希值,虽然我并不认为哈希值会匹配......值得一试。

还有其他比较表的方法,但回答你的问题,这两个平台上的两个本机函数。

答案 2 :(得分:0)

您可以在SQL Server中使用CHECKSUM()来计算多列哈希。

答案 3 :(得分:0)

如果您对Oracle系统的访问权限有限,并且尚未授予DBMS_CRYPTO.Hash()的执行权限,则仍可以使用DBMS_OBFUSCATION_TOOLKIT.MD5()在Oracle和SQL Server上生成相同的哈希值。您只需要确保将字符串转换为与运行SQL Server的计算机相同的代码页即可。我相信大多数北美Windows机器上的默认设置都是windows-1252 ANSI Latin 1; Western European (Windows)(来自https://docs.microsoft.com/en-us/windows/desktop/intl/code-page-identifiers

我不特别喜欢在WHERE子句中进行函数调用,因此我将SQL端哈希放入CTE中,然后加入到OPENQUERY结果中。

;WITH sqlHash AS
(
    SELECT s.PK
        ,UPPER(CONVERT(CHAR(32), HASHBYTES('MD5', s.Column1 + '|' + s.Column2 + '|' + s.ColumnN), 2)) AS sqlHash
    FROM sqltable s
)
SELECT s.PK
FROM sqlHash s
JOIN OPENQUERY
     ( oracleLinkedServer, '
     SELECT 
        PK
        ,CONVERT(UPPER(RAWTOHEX(
            SYS.DBMS_OBFUSCATION_TOOLKIT.MD5(input_string => "oraColumn1" || ''|'' || "oraColumn2" || ''|'' || "oraColumnN")
            )),''AL32UTF8'',''WE8MSWIN1252'') AS oracleHash
       FROM oracleTable' ) o ON o.PK = s.PK
WHERE s.sqlHash <> o.oracleHash

这里要指出的几件事可能不会立即显现。

首先,我在串联文本的每一列之间添加了竖线字符|。这是诸如"digital" + "aaron""digi" + "talaaron"之类的区别组合,它们会产生相同的哈希值,因为字符串将变成"digital|aaron""digi|talaaron",它们会产生不同的哈希值。

第二,当我们获得CTE中的SQL端时,该值以VARBINARY的形式返回。如果我们仅显示此值,则前导0x。但是,我们希望将其去除,并将值转换为比VARBINARY更有用的东西。因此,我们以CHAR(32)的样式转换为2