我目前正在开始将应用程序的postgres 8.4 db升级到9.4。实际的数据库迁移已经完美无缺,但是当针对9.4 DB运行时,一些应用程序查询没有返回奇怪的结果。我在C#中使用NpgSql v2.0.12.0库。该问题似乎与存储编码为base64字符串的文本数据的几个表有关。查询调用postgres解码函数以便将编码数据作为纯文本返回。例如:
SELECT
decode(user_name, 'base64')::text as user_name
FROM
login
WHERE
login_id = 123;
当提交到8.4 DB时,字符串将正确返回给应用程序。当提交到9.4 DB我得到
\x61646d696e6973747261746f72
在PgAdmin SQL工具中,两种情况下的结果都是正确的。我确定这可能是某种编码问题,但对于我的生活我无法弄明白 - 我用谷歌搜索了几个小时,挖了postgres文档并在这里无休止地搜索并最终拥有找不到我的问题的解决方案。希望有一些PostGres的人可以指出我正确的方向来解决这个问题。
答案 0 :(得分:1)
您一直依赖于将bytea
输出解释为当前编码中的字符串,即您的代码一直是错误的,但恰好有效。
使用较旧的PostgreSQL版本" escape" bytea文字的格式,对于7位ASCII字符看起来像纯文本,对非打包字符和8位字符使用八进制转义,例如
test=> SET bytea_output = 'escape';
SET
test=> SELECT convert_to('administrator á
', 'utf-8');
convert_to
----------------------------
administrator \303\241\012
(1 row)
后来的PostgreSQL版本默认为' hex'输出,将所有编码为十六进制:
test=> SET bytea_output = 'hex';
SET
test=> SELECT convert_to('administrator á
', 'utf-8');
convert_to
--------------------------------------
\x61646d696e6973747261746f7220c3a10a
(1 row)
所以你的应用程序无法假设bytea已经是文本了。
如果base64字符串是当前本地文本编码中的有效文本,则可以使用convert_from(decode(user_name, 'base64'), 'utf-8')
。但在这种情况下,您应该将其存储为普通text
而不是base64编码。
如果base64字符串在当前编码中不有效,例如它包含空字节,不能在client_encoding
中表示的字符等,然后你应该返回hex或base64表示并在客户端应用程序中解码它。