我们正在努力将数据库从MSSQL迁移到PostgreSQL数据库。在此过程中,我们遇到了一种情况,其中一个表包含NVARCHAR类型的password字段,并且该字段值从VARBINARY类型转换而来,并存储为NVARCHAR类型。
例如:如果我执行
SELECT HASHBYTES('SHA1','Password')`
然后它返回0x8BE3C943B1609FFFBFC51AAD666D0A04ADF83C9D
,然后如果将此值转换为NVARCHAR,则它将返回格式为"䏉悱゚얿괚浦Њ鴼"
的文本
我们知道PostgreSQL不支持VARBINARY,所以我们改用BYTEA,它返回二进制数据。但是,当我们尝试将二进制数据转换为VARCHAR类型时,它将返回十六进制格式
例如:如果在PostgreSQL中执行相同的语句
SELECT ENCODE(DIGEST('Password','SHA1'),'hex')
然后返回
8be3c943b1609fffbfc51aad666d0a04adf83c9d
。
当我们尝试将此编码文本转换为VARCHAR类型时,它返回的结果与8be3c943b1609fffbfc51aad666d0a04adf83c9d
是否有可能获得与从MSSQL服务器检索到的结果相同的结果?由于这些与密码字段相关,因此我们无意更改这些值。请建议需要做什么
答案 0 :(得分:0)
这听起来像是您正在获取包含加密哈希的字节数组,并且想要将其转换为字符串以进行字符串比较。这是一种进行哈希比较的奇怪方法,但可能取决于您在MSSQL端使用的编码方式。
如果您有一个字节数组,可以在使用的编码中将 转换为字符串(例如,不包含该编码的任何无效代码点或序列),则可以转换该字节数组为字符串,如下所示:
SELECT CONVERT_FROM(DIGEST('Password','SHA1'), 'latin1') AS hash_string;
hash_string
-----------------------------
\u008BãÉC±`\u009Fÿ¿Å\x1Afm+
\x04ø<\u009D
如果您使用的是Unicode,则此方法将完全无效,因为随机的二进制数组无法转换为Unicode,因为某些序列始终无效。您会收到如下错误:
# SELECT CONVERT_FROM(DIGEST('Password','SHA1'), 'utf-8');
ERROR: invalid byte sequence for encoding "UTF8": 0x8b
Here's a list of valid string encodings in PostgreSQL。找出您在MSSQL端使用的编码,然后尝试将其与PostgreSQL匹配。如果可以的话,我建议您更改您的业务逻辑以直接比较字节数组,因为这样不容易出错,而且应该会更快。
答案 1 :(得分:0)
然后返回0x8BE3C943B1609FFFBFC51AAD666D0A04ADF83C9D,然后依次返回 如果此值转换为NVARCHAR,则返回文本 格式为“䏉悱゚얿괚浦Њ鴼”
基于此,MSSQL将这些字节解释为UTF-16LE编码的文本。
使用PostgreSQL并且仅使用内置函数,您将无法获得该结果,因为PostgreSQL根本不使用或不支持UTF-16。 它还不支持字符串中的nul个字节,并且UTF-16中有nul个字节。
此问题解答:UTF16 hex to text提出了几种解决方案。
但是,改变业务逻辑以不依赖UTF-16将是您最好的长期选择。例如,十六进制表示形式更简单,更可移植。