PostgreSQL - 将二进制数据转换为Varchar

问题描述 投票:0回答:2

我们正在努力将数据库从MSSQL迁移到PostgreSQL数据库。在此过程中,我们遇到一种情况,其中表包含密码字段,该字段为NVARCHAR类型,并且此字段值已从VARBINARY类型转换并存储为NVARCHAR类型。

例如:如果我执行

SELECT HASHBYTES('SHA1','Password')` 

然后它返回0x8BE3C943B1609FFFBFC51AAD666D0A04ADF83C9D,反过来如果这个值转换成NVARCHAR然后它返回格式为"䏉悱゚얿괚浦Њ鴼"的文本

我们知道PostgreSQL不支持VARBINARY所以我们使用了BYTEA而它返回了二进制数据。但是当我们尝试将这个二进制数据转换为VARCHAR类型时,它返回十六进制格式

例如:如果在PostgreSQL中执行相同的语句

SELECT ENCODE(DIGEST('Password','SHA1'),'hex')

然后它返回8be3c943b1609fffbfc51aad666d0a04adf83c9d

当我们尝试将此编码文本转换为VARCHAR类型时,它返回与8be3c943b1609fffbfc51aad666d0a04adf83c9d相同的结果

是否有可能获得从MSSQL服务器检索到的相同结果?由于这些与密码字段有关,因此我们无意更改这些值。请告知需要做什么

postgresql varbinary bytea
2个回答
0
投票

听起来您正在使用包含加密哈希的字节数组,并且您希望将其转换为字符串以进行字符串比较。这是进行哈希比较的一种奇怪的方法,但可能取决于您在MSSQL端使用的编码。

如果您有一个可以在您正在使用的编码中转换为字符串的字节数组(例如,不包含任何无效的代码点或该编码的序列),您可以将字节数组转换为字符串,如下所示:

SELECT CONVERT_FROM(DIGEST('Password','SHA1'), 'latin1') AS hash_string;
         hash_string
-----------------------------
 \u008BãÉC±`\u009Fÿ¿Å\x1A­fm+
 \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匹配。如果您可以建议您更改业务逻辑以直接比较字节数组,因为这样会更不容易出错并且应该明显更快。


0
投票

然后它返回0x8BE3C943B1609FFFBFC51AAD666D0A04ADF83C9D,然后如果将该值转换为NVARCHAR,则它将返回“䏉悱얿괚얿괚Њ鴼format”格式的文本。

基于此,MSSQL将这些字节解释为以UTF-16LE编码的文本。

使用PostgreSQL并仅使用内置函数,您无法获得该结果,因为PostgreSQL根本不使用或支持UTF-16。它也不支持字符串中的nul字节,并且UTF-16中有nul个字节。

这个Q / A:UTF16 hex to text提出了几个解决方案。

但是,改变您的业务逻辑不依赖于UTF-16将是您最好的长期选择。例如,十六进制表示更简单,更便携。

© www.soinside.com 2019 - 2024. All rights reserved.