是否可以从两个数据库服务器生成哈希代码并进行比较?如何在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
答案 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
。