【问题标题】:Unicode normalization in PostgresPostgres 中的 Unicode 规范化
【发布时间】:2014-07-21 11:14:51
【问题描述】:

我有大量带有苏格兰和威尔士口音的地名(结合了严重、急性、抑扬符和 diareses),我需要将它们更新为它们的 unicode 规范化形式,例如,á 的较短形式 00E1 (\xe1)而不是 0061 + 0301 (\x61\x301)

我从 2009 年的旧 Postgres nabble 邮件列表中找到了一个解决方案,使用 pl/python,

create or replace function unicode_normalize(str text) returns text as $$
  import unicodedata
  return unicodedata.normalize('NFC', str.decode('UTF-8'))
$$ LANGUAGE PLPYTHONU;

这正如预期的那样有效,但让我想知道是否有任何方法可以直接使用内置的 Postgres 函数。我用convert_to尝试了各种转换,都是徒劳的。

编辑:正如 Craig 所指出的,以及我尝试过的一件事:

SELECT convert_to(E'\u00E1', 'iso-8859-1');

返回\xe1,而

SELECT convert_to(E'\u0061\u0301', 'iso-8859-1');

ERROR: character 0xcc81 of encoding "UTF8" has no equivalent in "LATIN1" 失败

【问题讨论】:

  • 所以你想要 precomposed 而不是 decomposed 形式?如SELECT E'\u00E1', E'\u0061\u0301';
  • 嗯。有趣的。我希望 Pg 在convert_to 之前进行组合和规范化,但事实并非如此。坦率地说,这似乎是一个错误,因为这意味着 convert_to(E'\u0061\u0301', 'iso-8859-1'); 失败但 convert_to(E'\u00E1', 'iso-8859-1') 成功。
  • @Craig,是的,第一条评论。是的,我尝试了这些转换并得到“在 LATIN1 中没有等效项”错误。如果您认为这是一个错误,您可以将其发布为答案,以便我接受吗?
  • 让我们先看看有没有其他人有想法。
  • @CraigRinger,好主意。我很高兴在 convert_to 函数中没有遗漏任何明显的东西。

标签: postgresql unicode plpython


【解决方案1】:

我认为这是一个 Pg 错误。

在我看来,PostgreSQL 应该在执行编码转换之前将 utf-8 规范化为预先组合的形式。显示的转换结果是错误的。

我将在 pgsql-bugs 上提出它……完成。

http://www.postgresql.org/message-id/53E179E1.3060404@2ndquadrant.com

你应该可以关注那里的帖子。

编辑:pgsql-hackers 似乎不同意,所以这不太可能很快改变。我强烈建议您在应用程序输入边界处规范化您的 UTF-8。

顺便说一句,这可以简化为:

regress=> SELECT 'á' = 'á';
 ?column? 
----------
 f
(1 row)

这是普通的疯狂谈话,但被允许。第一个是预先合成的,第二个不是。 (要查看此结果,您必须复制和粘贴,并且仅当您的浏览器或终端不规范化 utf-8 时才有效)。

如果您使用的是 Firefox,您可能无法正确看到上述内容; Chrome 可以正确呈现它。如果您的浏览器正确处理分解的 Unicode,您应该看到以下内容:

【讨论】:

  • 我花了很多时间试图规范这样的 unicode 异常,但始终无法正确解决。 NFD、NFC、NFKD、NFKC?这些中的每一个都解决了一些问题并创造了新的问题。我开始相信 UNICODE 本身的概念存在严重缺陷。欺骗人眼的方法太多,没有合适的方法来规范化。
  • @ErwinBrandstetter 我倾向于同意。确实需要一种方式来做事。看看 Tatsuo Ishii 的关于构图排除字符的帖子。可怕。唉,那艘船已经航行了。
  • @CraigRinger。感谢提交。
  • @ErwinBrandstetter。我很高兴我不是唯一一个被 unicode 弄得头都歪的人。有时它确实看起来过于复杂,尽管在计算机中表达众所周知的写作方案并非易事,显然:D
  • @CraigRinger。我从 Tom Lane 的回复中看到它被认为是一个功能而不是一个错误。正如我所说,我有一个解决方法,并且已经在客户端级别进行了更改,因此分解的表单不会首先被插入。不过,无论如何,感谢您的提交。
猜你喜欢
  • 2013-05-04
  • 1970-01-01
  • 2011-10-25
  • 1970-01-01
  • 2011-12-08
  • 2019-03-27
相关资源
最近更新 更多