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

时间:2018-09-05 12:02:32

标签: postgresql varbinary bytea

我们正在努力将数据库从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服务器检索到的结果相同的结果?由于这些与密码字段相关,因此我们无意更改这些值。请建议需要做什么

2 个答案:

答案 0 :(得分: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匹配。如果可以的话,我建议您更改您的业务逻辑以直接比较字节数组,因为这样不容易出错,而且应该会更快。

答案 1 :(得分:0)

  

然后返回0x8BE3C943B1609FFFBFC51AAD666D0A04ADF83C9D,然后依次返回   如果此值转换为NVARCHAR,则返回文本   格式为“䏉悱゚얿괚浦Њ鴼”

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

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

此问题解答:UTF16 hex to text提出了几种解决方案。

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