我有一个 LATIN9 编码的 Postgresql 数据库。
我最近将我的 Web 应用程序 (PHP) 从 iso_8859_15 (latin9) 迁移到了 UTF8。
因此,现在,客户可以在评论表单或联系表单等 Web 表单中指定 UTF-8 字符。
我从 PHP 以 UTF-8 编码打开 PG 连接(PHP 函数 pg_set_client_encoding('UTF8') 左右......)
这对于像“éàù”这样的标准字符很有效...... PG 能够将它们从 UTF-8 转换为 LATIN9(数据库编码)。但是如果有人插入一些外来字符,比如日文字符“日本语”,PostgreSQL 会抛出这样的错误:
ERROR: character with byte sequence 0xe6 0x97 0xa5 in encoding "UTF8" has no equivalent in encoding "LATIN9"
我知道我应该将我的数据库迁移到 utf8 来解决这个问题,但由于某些原因,我暂时不能这样做。
就我而言,我宁愿 PostgreSQL 保存我的字符串,删除它无法转换的字符,或者例如用“?”之类的符号替换它们。而不是抛出错误......
我想使事情像这样工作的唯一方法是在 LATIN9 中打开我的连接并使用像这样工作的 utf8_decode() PHP 函数(用“?”符号替换未知字符)
有没有可能以更好的方式做到这一点?也许是一个 PG 参数(但我在 postgresql.conf 中没有看到这样的参数)
或者有人对如何处理这个有其他想法?
谢谢,
PostgreSQL 不支持这个。它会定期请求,但没有人会在系统中实际实施它并说服开发团队这是一个合适的选项。
您将需要在客户端进行文本处理。在 PHP 中,在将文本发送到 PostgreSQL 之前,您需要过滤掉与数据库编码不匹配的字符。如何做到这一点完全是 PHP 特定的(可能从 iconv 支持开始)。您已经描述了一种方法来做到这一点,使用
utf8_decode
, 。使用
utf8_decode
实际上是不正确的,因为函数(根据文档)实际上假设输入是 ISO-8859-1,即 Latin-1。您使用的是 latin-9,即 ISO-8859-15。所以它会破坏你的一些输入字符,特别是欧元符号。请参阅ISO-8859-1 的更改。相反,请使用该iconv
功能。请参阅utf8_decode
函数文档中令人惊讶的有用注释。如果在过滤文本的过程中您在 PHP 中将其转换为 LATIN9,请记住您必须将您的设置
client_encoding
为 latin9,因为这是您将发送到 PostgreSQL 的文本的编码。这意味着结果也将采用 latin-9,因此您必须将 PostgreSQL 中的所有结果从 latin-9 转换回 PHP 的本机 utf-8。如果您使用
utf8_encode
从 PostgreSQL 转换您的 latin-9 输出以在 PHP 中使用,您将遇到与 latin-1 与 latin-9 相同的问题utf8_decode
。因此,如果可能,请尝试使用过滤器替换 latin-9 中不支持的字符,而无需实际将字符串转换为 latin-9。
client_encoding
如果您可以保持设置utf-8
并只是破坏您的字符串而不是转换它们,它将为您节省很多麻烦。综上所述,我强烈建议将数据库升级到 utf-8。将其保留在 latin-9 中的唯一原因是,如果您有其他客户端应用程序无法处理 latin-9 范围之外的字符(即它们依赖于 latin-9
client_encoding
)