PostgreSQL:编码“UTF8”的字符在plperl存储过程中的“LATIN1”中没有等价物

时间:2013-03-22 11:29:04

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

我有用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 encodend)可能有一些无效的字符,因为我得到的结果如下:

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()来尝试更改编码,但没有任何运气。有什么想法吗?

提前致谢。

1 个答案:

答案 0 :(得分:1)

我想这里发生的事情是strip_html_tags将HTML实体解码为原生Unicode代码点,表示为utf-8编码文本。 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编码的字节字符串 - 然后将它们解码回应用程序中的文本。我真的不推荐这个。