如何在Oracle和SQL-Server之间转换nvarchar 2

uajslkp6  于 2022-12-03  发布在  Oracle
关注(0)|答案(2)|浏览(281)

在我运行的SQL服务器中

SELECT HashBytes('MD5', CONCAT('A',convert(nvarchar,123),'456')) as mycol

并且得到了

0xC2E6DDD93A5E4A4FEC8162D4847BD3AA

在Oracle中,我运行

select standard_hash(concat('A',concat(cast('123' as nvarchar2(255)),'456')), 'MD5') from dual;

但我得到了

0x687A57C778D4AC73D90F1EB9290ED283

我在Oracle中做错了什么。我想有相同的输出!

sgtfey8w

sgtfey8w1#

Joel已经解释了这个问题,但是作为一种变体--因为Oracle discourages the use of the CONVERT function--您可以使用UTL_I18N包来进行转换:

standard_hash(utl_i18n.string_to_raw(n'A123456', 'AL16UTF16LE'), 'MD5')

这包含了MTO关于简化值的注解。它还假设数据库的国家字符集是AL 16 UTF 16,但从最初得到的结果来看似乎是这样。
如果需要,您可以继续构建值-也许'123'字符串来自一个表?-但是连接运算符比嵌套的concat()函数调用更容易使用:

select standard_hash(
  utl_i18n.string_to_raw('A' || cast('123' as nvarchar2(255)) || '456', 'AL16UTF16LE'),
  'MD5') as result
from dual;

| 结果|
| - -|
| 0xC 2 E6 DDD 93 A5 E4 A4 FEC 8162 D4847 BD 3AA指令集,可编程逻辑控制器|
fiddle

33qvvth1

33qvvth12#

md5算法不理解字符串;它只对字节数组进行操作。2因此字符串输入的确切字节编码很重要,因为即使是一个比特的差异也会完全改变哈希输出。
在本例中,两个数据库都已将字符串编码为UTF-16,但同样:The specific difference between Oracle and SQL Server is Endian-ness,SQL Server使用Little Endian编码,而Oracle使用Big Endian编码。您需要更改Oracle查询,使其生成与SQL Server具有相同Little Endian编码的字符串。
我想这个表达应该可以胜任:

standard_hash(convert(concat('',concat(cast('313' as nvarchar2(255)),'@12')),'AL16UTF16LE'), 'MD5')

您可以在下面的示例输入中看到它的作用:
https://dbfiddle.uk/wTZCgFJp
然而,这可能是一个枣手的问题,您应该在更广泛的可能输入上测试它,使用几种不同的字符类型来覆盖您的实时数据中可能包含的更多内容。

相关问题