Sybase字符集配置与转化
配置篇
2.1 如何配置字符集的转换类型
禁用字符集转换的配置方法 
在isql  环境中执行:
1> sp_configure “disable character set conversion”,1
2> go
“disable character set conversion”  参数默认配置值为0  ,即启用字符集转换。
如何配置字符集的转换类型
 把”enable unicode conversions”  参数设置为1  或者2  。当配置为1  时,此设置使用直接转换或Unicode  转换;当配置为2  时,此设置使用Unicode  转换;默 认配置值为0  ,使用直接转换。
在isql  环境中执行:
1> sp_configure ”enable unicode conversions”,1
2> go
2.2  如何配置服务器端缺省字符集
直接转换法
 直 接转换法是指直接使用Sybase  提供的实用程序,如UNIX  平台上使用sqlloc  命令或者编辑sqlloc.rs  脚本文件;Windows  平台使用 “  服务器配置”  图形化管理工具直接配置服务器端字符集。
使用直接转换法的条件是:
――  服务器中没有用户数据
――  对服务器中用户数据的损坏是可以接受的
――  绝对确定服务器中的数据只使用ASCII-7  字符集
间接转换法 
间接转换法相对于直接转换法而言,需要通过一下三步来完成配置工作:
1.   先将服务器端的数据使用bcp  命令导出
2.   再选择直接转换法之中的一种方式配置服务器端字符集
3.   再使用带有-J   参数的bcp  命令把数据导回服务器端
配置服务器端字符集的方法 sqlloc—  适用于UNIX  平台的命令 
在$SYBASE_OCS/bin  目录下执行:sqlloc  ,将出现一个图形化界面,在这个界面中您可以直接选择语言集,字符集,排序顺序,便很容易地就 完成了配置工作。
编辑sqlloc.rs  脚本文件
 将$SYBASE-ASE/init /sample_resource_files/sqlloc.rs  拷贝到$SYBASE_OCS/bin  目录下,按以下黑体字提示编辑该文件:
sybinit.release_directory: /home/sybase―――  输入Sybase  产品的安装路径
sqlsrv.server_name: SYB125―――  输入数据库服务器的名称
sqlsrv.sa_login: sa
sqlsrv.sa_password: ―――  输入sa  的口令,若为空,则什么也不填
sqlsrv.default_language: us_english―――  输入想要配置的语言集
sqlsrv.language_install_list: USE_DEFAULT
sqlsrv.language_remove_list: USE_DEFAULT
sqlsrv.default_characterset: cp850―――  输入想要配置的字符集
sqlsrv.characterset_install_list: USE_DEFAULT
sqlsrv.characterset_remove_list: USE_DEFAULT
sqlsrv.sort_order: binary―――  输入想要配置的排序顺序
# An example sqlloc resource file…
# sybinit.release_directory: USE_DEFAULT
# sqlsrv.server_name: PUT_YOUR_SERVER_NAME_HERE
# sqlsrv.sa_login: sa
# sqlsrv.sa_password:
# sqlsrv.default_language: french
# sqlsrv.language_install_list: spanish,german
# sqlsrv.language_remove_list: USE_DEFAULT
# sqlsrv.default_characterset: cp437
# sqlsrv.characterset_install_list: mac,cp850
# sqlsrv.characterset_remove_list: USE_DEFAULT
# sqlsrv.sort_order: dictionary
保存已经修改好的sqlloc.rs  脚本文件,执行以下命令:
sqllocres -r sqlloc.rs
注意屏幕上出现的提示信息,如无异常,则完成配置工作。
“  服务器配置”  图形化管理工具――  适用于Windows  平台 
“  服务器配置”  管理工具提供了一个易于操作的图形化管理平台,根据工具中提示的信息,很容易就完成了字符集的配置工作,这里就不多讲了,请参看相关文档说 明。
2.3  如何配置客户端缺省字符集 
配置客户端缺省字符集实际上就是对“$SYBASE\locales”  目录下locales.dat  文件的修改。
Windows  平台用写字板方式打开该文件,在UNIX  平台可以直接使用“vi”  命令打开该文件,我们会看到,该文将中所有字符集的配置都是以服务器端操 作系统平台名称分组的:
.
.
[aix]
locale = C, us_english, iso_1
locale = En_US, us_english, iso_1
locale = en_US, us_english, iso_1
locale = default, us_english, iso_1
locale = En_US.IBM-850, us_english, cp850
locale = en_JP, us_english, eucjis
locale = Fr_FR, french, cp850.
.
[axposf]
locale = C, us_english, iso_1
; Use Posix Locales, straight from the Posix Guidelines
locale = en_US.88591, us_english, iso_1
locale = fr_FR, french, iso_1
locale = zh_CN, chinese, eucgb
locale = zh_TW, tchinese, euccns
locale = ko_KR, korean, eucksc
locale = us_english.utf8, us_english, utf8
locale = default, us_english, iso_1
.
.
其中,操作系统名称放在每一组最开始的“[]”  中,而且请注意上面黑体字,每一组中都会存在一行“locale = default,…”  。我们要修改客户端的默认字符集,就是对这一行进行修改。
例如,某系统服务器端是SUN  平台,服务器端语言集为english  ,字符集为cp850  。我们要修改客户端字符集与服务器端一致,怎么做? 首先找到[SUN]  操作系统分组,然后修改“locale = default,…”  为“locale = default,us_English,cp850”  。
修改前:
[sun]
; from JLE, KLE, CLE, OS/4.1.1, man setlocale()
; and Sun Software Internationalization Guide (p/n 800-5972-08)
; use setenv LC_CTYPE, LC_MESSAGES, LANG
locale = C, us_english, iso_1
locale = fr, french, iso_1
locale = de, german, iso_1
locale = tr, us_english, iso88599
locale = zh, chinese, eucgb
locale = zh_CN, chinese, eucgb
locale = zh_TW, tchinese, euccns
locale = ko, korean, eucksc
locale = us_english.utf8, us_english, utf8
locale = default, us_english, iso_1
修改后:
[sun]
; from JLE, KLE, CLE, OS/4.1.1, man setlocale()
; and Sun Software Internationalization Guide (p/n 800-5972-08)
; use setenv LC_CTYPE, LC_MESSAGES, LANG
locale = C, us_english, iso_1
locale = fr, french, iso_1
locale = de, german, iso_1
locale = tr, us_english, iso88599
locale = zh, chinese, eucgb
locale = zh_CN, chinese, eucgb
locale = zh_TW, tchinese, euccns
locale = ko, korean, eucksc
locale = us_english.utf8, us_english, utf8
locale = default, us_english, cp850
保存该文件,就完成对客户端字符集的修改了。
这里,还要说明一种特殊情况:
为了满足服务器端某些应用的特殊需求,在服务器端设置了一个环境变量:LANG,  此时客户端字符集该如何设置呢?
例如,某系统服务器端是Windows 平台,使用语言集english ,字符集iso_1 ,并设置环境变量LANG=C 。我们要修改客户端字符集与服务器 端一致,怎么做?
首先找到[NT]  操作系统分组,然后在该组中加入一行
“locale = C,us_English,iso_1”
修改前:
[NT]
locale = enu, us_english, iso_1
locale = fra, french, iso_1
locale = deu, german, iso_1
locale = japanese, japanese, sjis
locale = chs, chinese, eucgb
locale = cht, tchinese, big5
; locale = kor, korean, eucksc
locale = us_english.utf8, us_english, utf8
locale = default, us_english, iso_1
修改后:
[NT]
locale = enu, us_english, iso_1
locale = fra, french, iso_1
locale = deu, german, iso_1
locale = japanese, japanese, sjis
locale = chs, chinese, eucgb
locale = cht, tchinese, big5
; locale = kor, korean, eucksc
locale = us_english.utf8, us_english, utf8
locale = default, us_english, iso_1
locale = C,us_English,iso_1
因此在修改客户端字符集之前,请先查看服务器端是否设置了环境变量“LANG“  ,再决定如何修改。
2.4  如何选择ASE  字符集使之支持简体中文字符 
目前在ASE 12.5  中支持中文字符的字符集有四种:CP936  ,EUCGB  ,UTF-8  和GB18030  。
其中EUCGB 字符集是基于GB2312-80 编码规范的,它的EUC (Extended Unix Code) 编码范围是第一字节0xA1~0xFE( 实际只用到0xF7) ,第二字节0xA1~0xFE 。
CP936 字符集是基于GBK 编码规范(实际上的国家标准是GB13000-90 ),是对GB2312 进行的扩展,第一字节为0×81~0xFE ,第二字 节分两部分,一是0×40~0×7E ,二是0×80~0xFE 。其中和GB2312 相 同的区域,字完全相同。
GB18030 字符集(国家标准号是GB18030-2000 )是2000 年3 月17 日发布的新的中文编码标准。它是GB2312 的扩充,采用单/ 双/ 四 字节编码体系结构,收录了27000 多个汉字以及臧文、蒙文、维吾尔文等主要的少数民族文字。Sybase 从ASE 12.5.0.3 之后开始支持GB18030 字符集。
UTF-8 字符集是现有ASCII 系统向Unicode 转换的一个过渡方案。它使用1-3 字节表示一个字符。简体中文的每个字符在utf8 中的长度基本上 都是3 个字节。它的最主要的优点是可以同时支持超过650 种语言的字符。缺点是针对中文字符来说,需要增加50% 的空间用来存储。还有一个问题是执行 sp_helptext 显示存储过程体的时候,有可能出现半个汉字。
一般来说,由于EUCGB 不支持国标一、二级字库以外的汉字,所以我们推荐用户在服务器端和客户端都使用CP936 字符集,或者在ASE 12.5.0.3 之后还可以使用GB18030 字符集,它可以支持一些比较生僻的汉字。它的不足是只有一种排序方式,即区分大小写的Binary 方式。所 以,如果需要使用支持中文字符集且不区分大小写的数据库时,就只能使用UTF-8 作为服务器端字符集,而客户端使用CP936 或GB18030 字符集。
另外,还有一种选择是,服务器端和客户端都使用iso_1 字符集,虽然iso_1 字符集并不直接支持中文字符,但我们将服务器端和客户端都设置成 iso_1 字符集后,系统也不会在客户端和服务器端进行字符转换,它只不过将一个汉字的两个字节当做两个单独字符来处理,一般情况下没有问题。但当执行 like 匹配查询的时候,它有可能返回不正确的结果,原因是服务器端是根据单字节去匹配查询条件的,很可能会有前一个汉字的第二字节与后一个汉字的第一字 节的内码组合符合查询条件,被服务器端作为查询结果返回来。
2.5  如何查看服务器端、客户端字符集 
查看服务器端字符集:
在isql  环境中执行:
1> sp_helpsort
2> go
查看客户端字符集:
在isql  环境中执行:
1> select @@client_csname
2> go
3.  错误处理篇 
3.1  为什么会出现字符集转换失败 
1.   当字符存在于客户端字符集中但在服务器字符集中不存在时,Adaptive Server  的字符集转换将报告转换错误,反之亦然。
用户会碰到下面的错误消息:
Msg 2402,Severity 16 (EX_USER):
Error converting client characters into server’s character set. Some character(s) could not be converted.
转换错误会阻止插入与更新语句的执行。如果发生此情况,请检查数据中有问题的字符并替换它们。
2.   当客户端发送数据时Adaptive Server  遇到转换错误,它用ASCII  码的问号(?)代替可疑字符所占字节,但查询批处理继续进行直到完成为止。
语句完成后,Adaptive Server  将发送一下消息:
Msg 2403,Severity 16 (EX_USER):
WARNING! Some character(s) could not be converted into client’s character set. Unconverted bytes were changed to question marks (`?’)  。
3. 当在客户端查询服务器端存储的数据时,当碰到中文汉字,在客户端显示乱码的现象,且没有任何提示信息。这是我们在应用中经常会碰到的现象,产生的原因是: 客户端与服务器端字符集不符。怎么解释呢?假设我们先期设置服务器端字符集为iso_1 ,客户端字符集也为iso_1, 然后我们从客户端向服务器端录入了 所有的数据;之后当我们需要查询时,使用的客户端,它的字符集为cp850 ,那么势必在该客户端上显示的字符集为乱码。
当出现这种情况时,最好配置客户端字符集为先期客户端使用的字符集或者配置客户端字符集与服务器端字符集一致,使得客户端字符集与服务器端字符集匹配。这 里我们不建议用户修改服务器端字符集,因为服务器中此时已经存在大量的数据,在使用直接转换方式时,由于源字符集与目的字符集中可能存在无法转换的字符而 导致Adaptive Server 无法启动;如果使用间接的转换方式,会增加工作量。
4.  附:如何安装cp936  字符集 
以在Windows  平台安装cp936  字符集为例,说明如何安装使用服务器中没有被默认安装的字符集。(  在ASE 12.5.0.3  版本中安装GB18030  字符集的方法类似)
(  这里SYBASE  的安装路径为c:\sybase)
1.c:\>cd \sybase\charsets\cp936
2.c:\sybase\charsets\cp936> charset -Usa -Psa_pass -Sserver_name binary.srt cp936
3.  在SQL  环境中 1>select name,id from syscharsets
2>go
找到name  为cp936  对应的id(  假设为171)
4.1>sp_configure "default character set id",171
2>go
5.  重启server  两次 
(注:  第一次启动后,server  会自动宕掉,需要第二次重启后才能使用)