如何正确设置 Informix GLS 及 CSDK 语言环境

本文介绍 GLS 相关知识,说明如何正确设置 Informix GLS 语言环境相关变量(DB_LOCALE,CLIENT_LOCALE),保证 Informix 数据库服务器、客户端能正确的支持中文字符和支持使用中文的对象名。说明在 CSDK 2.7 以上版本(当前最新版本为 CSDK 3.5)中对语言环境设置的要求。以及举例说明语言环境设置常见错误及解决办法。java

 

概述

IBM Informix 产品能够支持许多语言、文化和代码集。全部特定于文化的信息聚集于单个环境中,称为 Global Language Support (GLS)语言环境。除了 ASCII 美国英语以外,GLS 容许您在其余语言环境中工做并在 SQL 数据和标识中使用非 ASCII 字符。可使用 GLS 功能来与特定语言环境定制保持一致。语言环境文件包括特定于文化的信息,如货币和日期格式以及整理顺序。正则表达式

本文介绍 GLS 相关知识,说明如何正确设置 Informix GLS 语言环境相关变量(DB_LOCALE, CLIENT_LOCALE),保证 Informix 数据库服务器、客户端能正确的支持中文字符和支持使用中文的对象名。以及说明在 CSDK 2.7 以上版本(当前最新版本为 CSDK 3.5)中对语言环境设置的要求。sql

 

GLS 基本概念

字符(Character)是各类文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。字符集(Character set)是多个字符的集合,字符集种类较多,每一个字符集包含的字符个数不一样,常见字符集名称:ASCII字符集、GB2312字符集(简体中文)、BIG5字符集(繁体中文)、 GB18030字符集(亚洲字符集合)、Unicode( 经常使用 UTF-8) 字符集等。数据库

Informix GLS 语言环境对经常使用的字符集进行了命名及内部编码(采用 16 进制编码)管理。经过服务器端的文件:$InformixDIR/gls/cm3/registry 查看 GLS 字符名称、编码对照表。示例以下:服务器

 

字符集名称  编码  十六进制编码
 8859-1 819 # 0x0333 
 gb 57357 # 0xe00d 
 GB2312-80 57357 # 0xe00d 
 utf8 57372 # 0xe01c 
 big5 57352 # 0xe008 
 GB18030-2000 5488 # 0x1570

GLS 环境中不一样字符集名称可能对应同一个字符集编码,但一个字符集只能有一个编码,也就是说字符集编码才是惟一的。ui

GLS 环境中按照语言和地区把所支持的字符集分红不一样的目录。$InformixDIR/gls/lc11/ 语言 _ 地区 /,如中文大陆地区的目录为:$InformixDIR/gls/lc11/zh_cn/,该目录下有以下两个文件:1570.lco e00d.lco ,说明咱们在设置字符集时,咱们可使用 zh_cn.GB18030-2000 zh_cn.gb zh_cn.GB2312-80 三个不一样的名称。这里(zh_cn.gb 与 zh_cn.GB2312-80 对应相同的字符集)。编码

GLS 环境中不一样的字符集能够正确的进行转换,查看那些字符集能够正确转换的方法,查看目录 $InformixDIR/gls/cv9 目录下的是否存在指定字符集互相转换的文件。如该目录下有文件 e01ce00d.cvo 和 e00de01c.cvo 两个文件,表示 GLS 经过这两个转换文件支持 UTF-8 与 GB 之间的字符转换。url

Informix 经过 DB_LOCALE 和 CLIENT_LOCALE 来设置数据库的语言本地化支持设置。DB_LOCALE 和 CLIENT_LOCALE 的值由四部分组成 ( 第 4 部分为可选 ),字符集不区分大小写。spa

1          2            3          4 
 < 语言 >_< 国家和地区 >.< 字符集名 / 字符集编码 >[@modifier]

举例说明 :操作系统

CLIENT_LOCALE=en_us.8859-1 
 CLIENT_LOCALE=en_us.819 
 # 以上两个为同一字符集:819 为 8859-1 的编码
 DB_LOCALE=zh_cn.gb

GLS 字符集工做原理

Informix 数据库服务器端、客户端字符集的工做原理示意图见图 1。

图 1. IDS GLS 字符集处理过程示意图

图 1. IDS GLS 字符集处理过程示意图

DB_LOCALE 环境变量用途

  1. 在客户机应用程序和数据库服务器交换字符数据时,若是 DB_LOCALE 环境变量(在客户机计算机上)的值与 CLIENT_LOCALE 的值不一样,客户机应用程序将执行代码集转换。 代码集转换防止这两种代码集不一样时发生数据破坏。
  2. 在客户机应用程序请求链接时,它将包括 DB_LOCALE(若是已设置)的信息发送至数据库服务器。
  3. 在肯定如何设置服务器处理语言环境的数据库信息时,数据库服务器使用 DB_LOCALE。
  4. 在客户机应用程序尝试打开数据库时,数据库服务器将客户机应用程序传递的 DB_LOCALE 环境变量的值与数据库中存储的数据库语言环境进行比较。
  5. 当数据库服务器存取与语言环境相关的数据类型的列时,数据库服务器使用 DB_LOCALE 指定的语言环境。
  6. 当数据库服务器建立新数据库时,它将检查数据库语言环境(DB_LOCALE),以肯定如何在数据库的系统目录中存储字符信息。此信息包括诸如如何处理正则表达式、比较字符串以及确保代码集的正确使用的操做。

CLIENT_LOCALE 环境变量用途

  1. 在客户机应用程序和数据库服务器交换字符数据时,若是 CLIENT_LOCALE 环境变量的代码集与 DB_LOCALE(在客户机计算机上)的代码集不一样,客户机应用程序将执行代码集转换。代码集转换防止这两种代码集不一样时发生数据破坏。
  2. 在客户机应用程序请求链接时,它将包括 CLIENT_LOCALE 的信息发送至数据库服务器。
  3. 在肯定如何设置服务器处理语言环境的客户机应用程序信息时,数据库服务器将使用 CLIENT_LOCALE。
  4. 在 Informix ESQL/C 的预处理器处理源文件时,它接受以 CLIENT_LOCALE 的代码集编写的 C 源代码。 在 Informix ESQL/C 客户机应用程序执行时,将检查 CLIENT_LOCALE 以得到客户机语言环境的名称,该语言环境将对操做系统文件名、文本文件的内容以及日期、时间和数字数据的格式产生影响。
  5. 在数据库实用程序建立文件时,文件名和文件内容位于 CLIENT_LOCALE 指定的代码集中。在查找特定于产品的消息文件时,客户机应用程序将检查与客户机语言环境关联的消息目录。

四个语言环境的含义

  1. 客户机语言环境— Client locale

    客户机语言环境指定客户机应用程序用于执行读和写(I/O)操做的语言、地域和代码集。在客户机应用程序中,I/O 操做包括读取键盘输入或要发送至数据库的数据文件,以及将数据库服务器从数据库中检索的数据写入屏幕、文件或打印机。 经过 CLIENT_LOCALE 来设置客户机语言环境。

  2. 数据库语言环境— Database locale

    经过 DB_LOCALE 环境变量设置的数据库语言环境指定数据库服务器用于正确解释特定数据库中语言环境相关的数据类型(NCHAR 和 NVARCHAR)所需的语言、地域和代码集。DB_LOCALE 中指定的代码集肯定哪些字符在任何字符列中都是有效的,而且肯定数据库对象(如数据库、表、列和视图)的名称。数据库服务器使用 DB_LOCALE 环境变量指定的数据库代码集将数据传入和传出数据库。

  3. 服务器语言环境— Server locale

    数据库服务器使用 SERVER_LOCALE 环境变量指定的服务器代码集写文件(如调试和警告文件)。可是,数据库服务器不使用服务器语言环境来写入采用 Informix 专用格式的文件(数据库和表文件)。

  4. 服务器处理语言环境— Server processing locale

    数据库服务器使用数据库语言环境的代码集做为服务器处理语言环境的代码集 , 使用服务器处理语言环境来写入采用 Informix 专用格式的文件(数据库和表文件)。也就是说数据库服务器使用数据库语言环境(DB_LOCALE)来写入采用 Informix 专用格式的文件(数据库和表文件)。

创建数据库链接过程

在客户机应用程序请求与数据库的链接时,数据库服务器使用 GLS 语言环境执行如下步骤。

  1. 客户机应用程序发送语言环境信息到数据库服务器。
    • CLIENT_LOCALE( 未设置将采用默认 en_us.819);
    • DB_LOCALE( 未设置则不发送 )。
  2. 验证是否可以在客户机应用程序及其请求的数据库之间创建链接。

    对好比下两个语言环境:

    • 由客户机应用程序发送的 DB_LOCALE 指定的语言环境;
    • 存储在请求数据库的系统目录中的数据库语言环境。
      • 匹配,则创建链接。
      • 不匹配,提示没法链接到数据库。或者能够继续进行这样的链接,可是数据库服务器可能会不正确地解释它从客户机接收到的数据,那么只能靠本身来理解交换中数据的格式。
  3. 肯定服务器处理语言环境,按以下顺序肯定服务器处理语言环境:
    • 使用客户机定义的 DB_LOCALE;
    • 数据库语言环境中的环境变量 DB_LOCALE。

执行代码集转换

在客户机 / 服务器环境中,若是客户机或服务器计算机使用不一样的代码集来表示相同的字符,那么须要将字符数据从一种代码集转换为另外一种代码集。若是不进行代码集转换,那么一台计算机没法正确地处理或显示源自另外一台计算机的字符数据(在这两台计算机使用不一样的代码集时)。

什么时候执行代码集转换

只有在两个代码集(客户机和服务器处理语言环境,或服务器处理语言环境和服务器)不一样时,应用程序才必须使用代码集转换。如下状况是代码集不一样的可能缘由:

  1. 不一样的操做系统可能以不一样的方式对同一字符进行编码。
  2. 若是客户机语言环境和数据库语言环境指定不一样的代码集,客户机应用程序将执行代码集转换以便服务器计算机不会装入此类型的处理。
  3. 若是服务器语言环境和服务器处理语言环境指定不一样的代码集,数据库服务器将在写入和读取操做系统文件(如日志文件)时执行代码集转换。该转化不涉及到数据库数据的问题。

在图 1 中,黑点表示在客户机 / 服务器环境中可能发生代码集转换的两个时刻。

客户机应用程序代码集转换

当如下两个条件都为真时,客户机应用程序自动在客户机和数据库代码集之间执行代码集转换:

  • 客户机和数据库语言环境的代码集不匹配。
  • 客户机和数据库代码集之间的转换存在有效的目标代码集转换。

客户机应用程序开始执行时,它会比较客户机和数据库语言环境的名称,以肯定是否执行代码集转换。若是设置了 CLIENT_LOCALE 和 DB_LOCALE 环境变量,那么客户机应用程序使用这些语言环境名称来分别肯定客户机和数据库的代码集。若是未设置 CLIENT_LOCALE(且未设置 DBNLS),那么客户机应用程序假定客户机语言环境为缺省语言环境。若是未设置 DB_LOCALE(且未设置 DBNLS),那么客户机应用程序假定数据库语言环境与客户机语言环境(CLIENT_LOCALE 设置的值)相同。

若是客户机和数据库代码集相同,那么无需进行代码集转换。可是,若是代码集不匹配,客户机应用程序必须肯定这两个代码集是否可转换。若是客户机能够找到关联的代码集转换文件,那么两个代码集是可转换的。这些代码集转换文件必须存在于客户机计算机上。

举例说明:

客户机应用程序:CLIENT_LOCALE=en_us.1252 DB_LOCALE=en_us.8859-1 
客户机应用程序肯定它必须在 Windows 代码页 1252(客户机语言环境中)和 
ISO8859-1 代码集(数据库语言环境中)之间执行代码集转换。
若连接具备 GB(zh_cn.gb) 语言环境的数据库,那么数据库将设置 SQLWARN 警告,缘由是语言、地区和代码
集不一样。客户机应用程序将不正确地执行代码集转换。
它将继续在 Windows 代码页 1252 和 ISO8859-1 之间,而不是在 Windows 代码页 1252 和 zh_cn.gb 之间进行
转换。这种状况可能会致使数据破坏。应用程序将不会继续此连接。

设置字符集

Informix 经过 DB_LOCALE 和 CLIENT_LOCALE 来设置数据库的语言本地化支持设置。

数据库服务端

在建立数据库时(为了统一系统数据库与应用数据库的字符集,在建立数据库实例时),请按以下步骤设置数据库的 DB_LOCALE 值。

1. 设置环境变量 DB_LOCALE 
 set DB_LOCALE=zh_cn.gb 
 2. 建立数据库 create database dbname 
 3. 验证当前数据库字符集
 SELECT dbs_collate FROM sysmaster:sysdbslocale 
 WHERE dbs_dbsname = ‘ dbname ’

客户端

当咱们使用 ODBC,JDBC 链接数据库时,咱们须要在链接信息中正确设置语言环境变量:DB_LOCALE 和 CLIENT_LOCALE。

设置语言环境变量
 DB_LOCALE=zh_cn.gb 
 CLIENT_LOCALE=zh_cn.gb

ODBC:

下图为 WINDOWS 环境下 ODBC 语言环境设置示意图。

图 2. 在 ODBC 中设置语言环境

图 2. 在 ODBC 中设置语言环境

UNIX 环境下须要在 odbc.ini 文件中定义:

在 odbc.ini 文件中定义以下两项数据库语言环境变量
 DB_LOCALE=zh_cn.gb 
 CLIENT_LOCALE=zh_cn.gb

JDBC:

在使用 JDBC 链接数据库时,咱们须要在链接数据库的 URL 中设置数据库语言环境变量:DB_LOCALE 和 CLIENT_LOCALE。示例以下:

String url = "jdbc:Informix-sqli://10.127.1.11:8001/testdb:
 InformixSERVER=servername;user=user;password=password;
 DB_LOCALE=zh_CN.gb;CLIENT_LOCALE=zh_CN.gb";

 

常见字符集设置问题

在 Informix 数据库字符集设置与使用过程,咱们常会遇到一些字符集相关错误,知道了错误产生的缘由,就能够很容易解决问题。这里咱们总结了几种常见的字符集设置相关问题。

Error -23101 Unable to load locale categories

当设置的 DB_LOCALE 和 CLIENT_LOCALE 的字符集对应的如下文件不存在时,出现该错误。

  • - $InformixDIR/gls/lc11/DB_LOCALE's( 语言 _ 地区 )/(db 的 16 进制编码 ).lco
  • - $InformixDIR/gls/lc11/CLIENT_LOCALE's( 语言 _ 地区 )/( db 的 16 进制编码 ).lco
  • - $InformixDIR/gls/lc11/CLIENT_LOCALE's( 语言 _ 地区 )/( client 的 16 进制编码 ).lco

举例说明:

DB_LOCALE = en_us.utf8 #(对应的 16 进制编码为:e01c)
 CLIENT_LOCALE = zh_cn.gb18030-2000 #(对应的 16 进制编码为:1570)
 如下 3 个文件必须存在,缺任意文件将报 Error -23101。
  - $InformixDIR/gls/lc11/en_us/e01c.lco 
  - $InformixDIR/gls/lc11/zh_cn/e01c.lco 
  - $InformixDIR/gls/lc11/zh_cn/1570.lco

Error -23104 Error opening required code-set conversion object file

当设置的 DB_LOCALE 和 CLIENT_LOCALE 的字符集对应的如下转换文件不存在时,会出现该错误。固然只有当 DB_LOCALE 和 CLIENT_LOCALE 的字符集不一致时才会须要转换,若是一致则不会出现 -23104 错误。

- $InformixDIR/gls/cv9/ccccdddd.cvo 
 - $InformixDIR/gls/cv9/ddddcccc.cvo

其中:cccc 为 CLIENT_LOCALE 字符集编码对应的 16 进制值

dddd 为 DB_LOCALE 字符集编码对应的 16 进制值

举例说明:

DB_LOCALE = en_us.utf8 #(对应的 16 进制编码为:e01c)
 CLIENT_LOCALE = zh_cn.gb18030-2000 #(对应的 16 进制编码为:1570)
 如下 2 个文件必须存在,缺任意文件将报 Error -23104。
  - $INFOMRIXDIR/gls/cv9/e01c1570.cvo 
  - $INFOMRIXDIR/gls/cv9/1570e01c.cvo

Error -23197 Database locale information mismatch

当出现以下状况时,出现 -23197 错误。

  1. 定义的 DB_LOCALE 值与数据库的使用的值(数据库建立时使用的 DB_LOCALE 值)不一致;
  2. 经过 SET COLLATION 语句定义 DB_LOCALE 值与数据库的使用值不一致 ;

举例说明:

数据库的 LOCALE= en_us.8859-1 
 能够经过以下 SQL 读取当前数据库的 LOCALE 值
 SELECT dbs_collate FROM sysmaster:sysdbslocale WHERE dbs_dbsname = ‘ dbname ’ 
 客户端 DB_LOCALE 设置以下(注意:若是没有设置 DB_LOCALE,将使用在服务器计算机上设置的 DB_LOCALE),则会出现 -23197 错误DB_LOCALE = zh_cn.gb

Error -201,-202 数据库提示语法错误

Error -201,-202 数据库提示语法错误,不支持中文对象名,如中文表名、字段别名、视图名。该类错误提示缘由是当前数据库的 DB_LOCALE 设置问题。

若是数据库的 DB_LOCALE 设置为 zh_cn.GB18030-2000,则数据库就能够支持中文对象名。

举例说明:

DB_LOCALE = zh_cn.GB18030-2000 的数据库,能够支持以下中文对象名,不然将提示语法错误。
 Select c1 第一列 from test_cn; 
 Create table 中文表名 (c1 integer, 中文列名 integer); 
 drop table 中文表名 ; 
 若相似 SQL 不能运行,请核查数据库的 DB_LOCALE 值。
 SELECT dbs_collate FROM sysmaster:sysdbslocale WHERE dbs_dbsname = 'dbname'

乱码问题

Informix 字符出现乱码问题,或者不能正确显示中文字符。问题的缘由是客户端 CLIENT_LOCALE 设置的值与 DB_LOCALE 值不一致,并且二者对应的字符集之间不能正确进行转换。须要从新设置 CLIENT_LOCALE 与 DB_LOCALE 的值,确保二者一致或者能够正确相互转换。

时间格式问题

Informix 数据库的时间格式由数据库服务器端环境变量 GL_DATE GL_DATETIME 控制,默认的字符集下默认的时间格式为:

GL_DATE="%m/%d/%iy" 
 DATETIME="%iY-%m-%d %H:%M:%S"

可是,当咱们设置了 DB_LOCALE 为 zh_cn.gb 的情形下,而没有设置 GL_DATE,DATETIME,则时间格式会采用 CLIENT_LOCALE 的值,在 zh_cn.gb 状况下,会出现:“2009 年 10 月 2 日”的日期格式,若是咱们以前系统采用默认的时间格式的状况下,就会出现时间格式不匹配的错误。若是咱们仍然须要采用默认的时间格式,咱们须要在数据库服务端修改时间格式环境变量便可:

GL_DATE="%m/%d/%iy" 
 DATETIME="%iY-%m-%d %H:%M:%S"

 

GLS 对 CSDK 版本要求

CSDK2.8 及以上版本中(目前最新版本为 CSDK3.5),为了正确支持语言文字的处理,Informix GLS 语言环境下要求正确设置数据库服务器语言环境及客户端语言环境。在中文语言环境下,咱们应该按以下要求设置服务器端和客户端语言环境。

数据库服务端:

在建立数据库时(为了统一系统数据库与应用数据库的字符集,在建立数据库实例时),请按以下步骤设置数据库的 DB_LOCALE 值。

1. 设置环境变量 DB_LOCALE 
 set DB_LOCALE=zh_cn.GB18030-2000 
 2. 建立数据库 create database dbname 
 3. 验证当前数据库字符集
 SELECT dbs_collate FROM sysmaster:sysdbslocale 
 WHERE dbs_dbsname = 'dbname'

客户端:

当咱们使用 ODBC,JDBC 链接数据库时,咱们须要在链接信息中正确设置语言环境变量:DB_LOCALE 和 CLIENT_LOCALE。

设置语言环境变量
 DB_LOCALE=zh_cn.GB18030-2000 
 CLIENT_LOCALE=zh_cn.GB18030-2000

数据库不可以脱离字符集独立存在,它必定属于某种字符集。

CSDK2.7 版本,IDS 默认状况下使用 Garbage In, Garbage Out 模式处理中文字符,若数据库服务器上的 DB_LOCALE 采用默认的 en_us.8859-1 字符集,可以正常支持中文字符。可是升级到 CSDK2.8 及以上版本时,再也不支持 Garbage In, Garbage Out 模式,将出现乱码问题。iso-8859_1字符集的数据库只支持单字节。虽然能够往里面保存多字节的数据,可是数据库自己只是简单的认为这些数据只是单字节的数据。不管你存入的是双字节的中文,仍是4字节的unicode数据,数据库自己只是把它当为单字节而已。

 

客户端经过jdbc链接上数据库,并提取数据后,数据按照数据库默认的编码方式被提取到客户端。客户端要将其转换成unicode。由于jdbc是基于java的,而java内部所有是unicode编码。那么在客户端进行转换的时候,就有问题了,到底按哪一种格式转?

若是保存在数据库中的数据都是iso-8859_1中包含的字符,那么这样操做没错。可是若是是数据中有中文,那么这样操做就错了。

例如,汉字“中文”的ascii码为0xD6 0xD0 0xCE 0xC4,而经常使用的汉字codeset为cp936。若是按照cp936转unicode,则转换的结果是0xE4 0xB8 0xAD 0xE6 0x96 0x87;若是按照iso-8859_1转换则结果是0xC3 0x96 0xC3 0x90 0xC3 0x8E 0xC3 0x84.

你看,一样的数据,就是由于指定不一样的原始字符集,致使转换成unicode的时候,结果大相径庭。因此在用jdbc链接数据库的时候,有必要把这个转换关系给说清楚。

在informix jdbc中是经过newcodeset来讲明问题的。

在这里,咱们就要说清楚,数据库是按什么字符集存放数据的,取到客户端java时,这些数据须要按照什么样的字符集转换成unicode。

再或者更改数据库的字符集(设置 DB_LOCALE=zh_cn.GB18030-2000,从新建立数据库),而后按本文中描述的方法进行 DB_LOCALE 与 CLIENT_LOCALE 的设置方法进行处理。若在实际环境下重建数据库成本过高,能够考虑以下步骤进行解决 ODBC 支持中文的问题。

复制代码

数据库服务器端:
 1. 设置环境变量: IFMX_UNDOC_B168163=1 
 2. 将 en_us.8859-1 字符集文件拷贝到 zh_cn 目录下
     cd $INFORMIXDIR/gls/lc11 
     cp ./en_us/0333.lco ./zh_cn 
 3. 从新启动 IDS 
客户端:
设置语言环境:
     l DB_LOCALE=zh_cn.GB18030-2000 
     l CLIENT_LOCALE=zh_cn.GB18030-2000

对于 JDBC 咱们能够经过 NEWCODESET 来解决该问题:

  newcodeset的格式以下:
  newcodeset=jdk codeset, ifx codeset,ifx codenum

  jdbc的URL连接信息以下:

  URLString = "jdbc:Informix-sqli://9.125.66.130:6346/dbname:InformixSERVER=servername; NEWCODESET=GB18030-2000,8859-1,819; CLIENT_LOCALE=en_US.8859-1; DB_LOCALE=en_US.8859-1;"

总结

在简体中文应用环境下,请使用 zh_cn.GB18030-2000 字符集,在须要 unicode 的应用环境下,能够采用 en_us.utf8 字符集。

举例说明:采用 zh_cn.GB18030-2000字符集

数据库服务器端:
在建立数据库实例前,设置环境变量
 DB_LOCALE=zh_cn.GB18030-2000 
 CLIENT_LOCALE=zh_cn.GB18030-2000 
建立数据库
数据库客户端端:
须要在 setnet3二、ODBC、JDBC 链接中配置
 DB_LOCALE=zh_cn.GB18030-2000 
 CLIENT_LOCALE=zh_cn.GB18030-2000

举例说明:采用 utf8字符集

数据库服务器端:
在建立数据库实例前,设置环境变量
 DB_LOCALE=en_us.utf8 
 CLIENT_LOCALE= en_us.utf8 
建立数据库
数据库客户端端:
须要在 setnet3二、ODBC、JDBC 链接中配置
 DB_LOCALE= en_us.utf8 
 CLIENT_LOCALE= en_us.utf8

特别注意,在安装数据库前请设置好环境变量 DB_LOCALE 为规划的字符集,由于数据库一旦建立就不能修改其字符集,除非从新建立。在默认状况下将采用 en_us.8859-1。

相关文章
相关标签/搜索