【问题标题】:Informix Upper() not working with French charactersInformix Upper() 不适用于法语字符
【发布时间】:2018-01-24 17:54:24
【问题描述】:

upper() 函数似乎不会将 ë 等法语字符大写。

如何在使用大写时为法语字符添加重音支持?

-- Returns 0 rows
SELECT * FROM TABLE
WHERE UPPER(NAME) = "NOËLLE";

我们使用的是 Informix 11.10,语言环境设置为 en_us.8859-1

【问题讨论】:

  • 您使用的是哪个版本的 Informix?数据库配置为使用哪个代码集(区域设置)?您的数据输入的是哪个代码集(区域设置)?当我使用配置了DB_LOCALE="en_us.utf8"(并且CLIENT_LOCALE 也设置为相同)的数据库进行测试时,UPPER 函数适用于 UTF-8 数据。在另一个带有DB_LOCALE=fr_fr.8859-15 的数据库中,UPPER 函数也可以在 885015 个字符上正常工作。复制问题中的文字没有帮助;它采用 UTF-8 格式——但这可能是也可能不是您正在使用的代码集。该映射适用于 NVARCHAR 和 VARCHAR 列。
  • JFTR:我在运行 Informix 12.10.FC9W1 的古董 Linux 机器(我认为是 RedHat 5.3)上进行了测试(不是古董,虽然不是最新版本)。我是从 Mac 上的 Unicode 终端驱动它的。从 UTF-8 数据创建 8859-15 重音数据很有趣——锐利的工具和tr 的知识完成了它,但如果我对iconv 足够了解,它可能会更轻松地完成这项工作。
  • 我们使用的是 Informix 版本 11。我们所有数据库上的代码集都是 en_us.8859-1。
  • 11.10 或 11.50 或 11.70?第一次和最后一次之间有相当长的时间。我会查看en_us.8859-1 数据库,看看我发现了什么。
  • @JonathanLeffler 感谢您的帮助。它是 11.10 版

标签: sql ascii informix extended-ascii


【解决方案1】:

与很多东西一样,问题在于历史和大客户的复合。

Informix 的默认en_us.8859-1 语言环境不为重音字符进行大小写映射,这与几乎任何其他语言环境不同。您应该可以使用另一种方法-en_us.8859-1@extn。您可以在文件0333extn.lco$INFORMIXDIR/gls/lc11/en_us 目录中找到它(名称背后有一个基本原理;解释起来很复杂)。

不幸的是,AFAICT,您必须使用替代语言环境重建数据库才能使其正常工作 - 但当您这样做时,它确实有效。

演示代码很棘手——您在浏览器中看到的代码是用 UTF-8 而不是 8859-1 编码的。因此,您必须知道如何将数据从一个代码集转换为另一个代码集——iconv 命令可能是您最好的朋友(它比使用我的临时工具更容易)。

我创建了以下文件 (UTF8) — french-utf8.sql:

begin;
create table french_test(name varchar(32) not null);
insert into french_test values("noëlle");
insert into french_test values("ç'est rien");
insert into french_test values("être");
insert into french_test values("à la mode");
insert into french_test values("café au lait");
select name, upper(name) from french_test;

有一个BEGIN,但没有COMMIT,因此对数据库的更改不是永久性的(事务,包括 CREATE TABLE 语句,被回滚)。

可以使用以下方法将其转换为 8859-1:

iconv -f utf8 -t iso-8859-1 french-utf8.sql > french-8859-1.sql

将重音字符映射到\xXY 十六进制转义,输出变为:

begin;
create table french_test(name varchar(32) not null);
insert into french_test values("no\xEBlle");
insert into french_test values("\xE7'est rien");
insert into french_test values("\xEAtre");
insert into french_test values("\xE0 la mode");
insert into french_test values("caf\xE9 au lait");
select name, upper(name) from french_test;

针对普通的en_us.8859-1 数据库运行,输出为:

no\xEBlle|NO\xEBLLE
\xE7'est rien|\xE7'EST RIEN
\xEAtre|\xEATRE
\xE0 la mode|\xE0 LA MODE
caf\xE9 au lait|CAF\xE9 AU LAIT

如您所见,UPPER 不会更改重音字符,这是您正在/正在观察的问题。

针对使用en_us.8859-1@extn(同时设置DB_LOCALECLIENT_LOCALE)创建的数据库运行,输出为:

no\xEBlle|NO\xCBLLE
\xE7'est rien|\xC7'EST RIEN
\xEAtre|\xCATRE
\xE0 la mode|\xC0 LA MODE
caf\xE9 au lait|CAF\xC9 AU LAIT

在这里您可以看到输出已将\xE7 映射到\xC7,其他字符也是如此。


如果您不能使用en_us.8859-1@extn 语言环境,那么您可能会被简化为The TTG Guy 在其answer 中显示的REPLACE 操作序列。 Informix 还没有用于批量映射字符的 TRANSLATE 函数。

【讨论】:

  • 哇,答案很好,信息量很大。我现在更清楚地了解这种情况,并且根据您的建议,切换到不同的语言环境似乎是保持代码清洁的最佳解决方案。感谢您的帮助!
【解决方案2】:

您可以对要更改的每个字符使用嵌套的替换语句。例如:

SELECT * FROM TABLE
WHERE REPLACE(REPLACE(UPPER(NAME),"ë","Ë"),"é","É")  = "NOËLLE";

以下是全部:

SELECT * FROM TABLE
WHERE REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( REPLACE( 
UPPER(NAME),"à","À"),"â","Â"),"ä","Ä"),"æ","Æ"),"ç","Ç"),"é","É"),"è","È"),"ê","Ê"),"ë","Ë"),"î","Î"),"ï","Ï"),"ô","Ô"),"œ","Œ"),"ù","Ù"),"û","Û"),"ü","Ü")  = "NOËLLE";

【讨论】:

  • 没错,但是那很乏味
猜你喜欢
  • 2016-05-22
  • 2017-01-16
  • 1970-01-01
  • 2015-08-20
  • 2015-03-30
  • 1970-01-01
  • 2013-01-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多