【问题标题】:PostgreSQL: character of encoding "UTF8" has no equivalent in "LATIN1" in plperl stored procedurePostgreSQL:编码“UTF8”的字符在 plperl 存储过程中的“LATIN1”中没有等价物
【发布时间】:2013-03-22 11:29:04
【问题描述】:

我有这个用 Pl/Perl 编写的存储过程:

CREATE FUNCTION strip_html_tags(text) RETURNS TEXT AS $$
    use HTML::Strip;
    my $hs = HTML::Strip->new();
    my $clean_text = $hs->parse($_[0]);
    $hs->eof;
    return $clean_text;
$$ LANGUAGE plperlu;

我的数据库中有一些字段(LATIN1 编码)可能有一些无效字符,因为我得到如下内容:

db=# select strip_html_tags(field) from table;
ERROR:  character 0xe2809c of encoding "UTF8" has no equivalent in "LATIN1"
CONTEXT:  PL/Perl function "strip_html_tags"

我尝试使用 PostgreSQL 的 convert() 和 convert_from() 来尝试更改编码,但没有任何运气。有什么想法吗?

提前致谢。

【问题讨论】:

    标签: postgresql stored-procedures utf-8 latin1 plperl


    【解决方案1】:

    我想这里发生的事情是strip_html_tags 正在将 HTML 实体解码为以 utf-8 编码文本表示的本机 Unicode 代码点。 0xe2809c 解码为 utf-8 字节序列是 the unicode code point U+201c LEFT DOUBLE QUOTATION MARK - the character ,这是完全可信的,因为您可以从 HTML 中的解码转义中获得,尤其是由 GUI 编辑器或 MS Word 生成的 HTML。它会在 HTML 中表示为““(十进制)或“(十六进制)。

    由于您的数据库编码是 latin-1,因此您无法在数据库中表示许多这些解码的字符。

    如果您要使用完整的 unicode 数据,您真的应该考虑将数据库更改为 utf-8。如果你的数据库真的在latin-1 而不是(呃)SQL_ASCII,这通常并不难;只需转储数据库,使用ENCODING 'utf-8' 创建一个新数据库并将数据加载到其中进行验证和检查。针对转换后的数据库测试您的应用程序,并确保它们正确处理 unicode 文本。当您满意时,停止您的应用程序,再次转储数据库,再次重新加载,重命名旧数据库,然后将新数据库重命名为与旧数据库相同的名称。

    如果您愿意修改您的 HTML,您可以use Perl modules features to do a lossy encoding conversion from UTF-8 to Latin-1。有一些 Perl 模块会做一些事情,比如用" 替换,用-(减号)替换(破折号)等,并且可以去除不可替换的字符或用替代字符替换它们像“?”这样的字符。这是一个单向有损的转换;如果您不保留原始未更改版本的副本,则无法取回原始数据。

    您唯一的其他选择是将数据返回为bytea - utf-8 编码的字节字符串 - 然后将它们解码回应用程序中的文本。我真的不推荐这个。

    【讨论】:

      猜你喜欢
      • 2013-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-22
      • 1970-01-01
      • 2012-02-08
      • 1970-01-01
      相关资源
      最近更新 更多