轉自 :http://tech.ccidnet.com/art/9871/20070413/1060729_1.html
1. 概念
一、什麼是字符集?
字符集是字符(包含字母,數字,符號和非打印字符等)以及所指定的內碼所組成的特定的集合。通常一個字符集包含一個字母表中的字符,例如拉丁字母表被使用在英語語言中,那麼如果要使用拉丁字符,就要配置使用英語語言集中的特定的字符集合――拉丁語言字符集。這裏爲什麼特指了是英語語言集呢?因爲字符集是基於某種操作系統平臺和某種語言集支持的。語言集的集合被稱爲語言組,它可能包含一種或多種語言。本地字符集是基於特定語言組中所包含的一種或多種語言支持的,在特定操作系統平臺上編碼的集合。
在Client/Server系統中,支持多語言的數據處理,但是所有的語言必須屬於同一個語言組。例如,從下表可以看出,如果服務器中的數據用組1中的字符集,則同一數據庫中可以有法語,德語,英語以及該組中的其它語言。而在這個數據庫中就不能同時存儲日語,法語了。
這裏請注意一個非常特別的字符集—Unicode—它支持世界上超過650種語言的國際字符集。Unicode允許在同一服務器上混合使用不同語言組的不同語言。
表1-1 Adaptive Server支持的語言和字符集
注意:表中所顯示的所有字符集,因爲任何字符集的前128(十進制)個字符都包含拉丁字母表,所以所有字符集都支持英語。各字符集中前128個字符之外的字符各不相同,用於支持不同的本地語言字符。
二、什麼是排序順序?
每種字符集都有一種或多種排序順序,Adaptive Server使用它們存儲數據。排序順序與特定的語言或語言組及特定的字符集聯繫密切,不同的語言對同樣字符的排序是不同的,因此,需要特定語言的排序順序,以便正確地對字符進行排序。另外,排序順序與特定地字符集也密切相關,對於特定字符集可使用的排序順序位於字符集目錄的排序順序定義的文件中(.srt文件)。
有關字符集及其可用排序順序的列表,如下所示:
表1-2可用的排序順序
排序順序用於
――創建索引
――將數據存入按索引排序的表
――指定order by子句
對於不同類型排序順序的解釋
二進制排序順序:
對於所有字符集都至少提供一個二進制排序順序,這一排序順序基於字符集中分配給代表每個字符的代碼(“二進制”代碼)的算數值,適用於每個字符集的前128個字符和亞洲語言。當字符集支持一種以上的語言時,二進制排序順序將會得出不正確的結果,這時就應該選擇其它排序順序了。
字典排序,區分大小寫,區分重音:
分別對大寫和小寫字母進行排序。字典排序順序識別字母的各種重音形式,並將它們排在相關聯的非重音字母之後。
字典排序,不區分大小寫,區分重音:
按字典順序排序,大寫字母與小寫字母等同,在排序結果中大小寫字母混合使用。對於避免表中名稱的重複條目很有用。
字典排序,不區分大小寫,區分重音,具有優先級:
在排序時不區分大小寫,在所有其它條件相同時,大寫字母具有高的優先級(即大寫字母先出現)。
當order by子句中指定的列與表的聚簇索引鍵值相匹配時,使用這種排序順序可能導致大表性能降低,因此,不建議使用這種排序順序,除非特意要求大寫字母排在小寫字母之前。
字典排序,不區分大小寫,不區分重音:
將加重音格的字母與未加重音格的相關聯字母同等對待,它在排序中混合了重音字符。
三、什麼是字符集轉換?
爲保持客戶端與服務器之間的數據完整性,數據必須在字符集之間進行轉換,目的是跨機器和字符集使用時,確保“a”還是“a”,此過程就是字符集轉換。
字符集轉換的方式
本地字符集的轉換:
Adaptive Server支持屬於同一語言組的本地字符集之間的轉換。如果服務器把一種本地字符集作爲它的缺省值,則客戶端字符集必須屬於同一個語言組,此時可以在服務器上瀏覽所有客戶端提交的數據。如下圖:
圖1-3 服務器端和客戶端字符集屬於同一語言組
本圖中,服務器端與客戶端使用的語言集與字符集都同屬於組1(見表1-1),那麼他們之間實現的就是本地字符集轉換方式。
Unicode系統中的轉換方式:
在Unicode系統中,由於服務器的缺省字符集爲UTF-8,所以客戶端字符集可以是任何語言組中的一種本地字符集。如下圖:
圖1-4Unicode系統中的字符集轉換
上圖中來自每一個客戶端的數據經過服務器和每個客戶端時,都會被正確轉換,而無論每一個客戶端選擇的時哪個語言組的字符集,原因是ASE服務器端選擇了缺省字符集UTF-8.
字符集轉換類型
直接轉換:
支持同一語言組內兩種本地字符集之間的轉換。例如,Adaptive Server支持CP437與CP850之間的轉換,因爲他們同屬於第1語言組。
Unicode轉換:
Unicode轉換可應用於所有本地字符集,在兩種本地字符集之間進行轉換時,Unicode轉換方式把Unicode作爲中間字符集。例如,在服務器缺省字符集CP437和客戶端字符集CP860之間進行轉換時,CP437先被轉換成Unicode,Unicode再轉換成CP860。
Unicode轉換方式既可以用於服務器缺省字符集UTF-8,還可用於本地字符集。除非使用服務器缺省字符集UTF-8,否則您必須專門配置您的服務器才能使用Unicode轉換方式(配置方法請參看配置篇之如何配置字符集的轉換類型)。
如何選擇字符集的轉換方式
這將取決於系統的類型。
在非Unicode系統中,服務器和客戶端的字符集爲本地字符集,因此可以使用Adaptive Server直接轉換,但是有些字符集沒有直接轉換,這種情況就必須使用Unicode轉換了。
如下表所示:
表1-5 字符集轉換方式
――如果系統中使用的所有字符集都在表1-5的列1中,則使用直接轉換。前提是所有字符集同屬於一個語言組。
――如果系統中使用的所有字符集都在表1-5的列2中,或者有些在列1中,有些在列2中,那麼必須配置服務器使用Unicode轉換方式。前提是所有字符集同屬於一個語言組。
在Unicode系統中,如果服務器缺省字符集爲Unicode UTF-8,那麼所有的轉換將在UTF-8與客戶端使用的本地字符集之間進行,因此,在Unicode系統中,只能使用Unicode轉換。
2. 配置
一、 如何配置字符集的轉換類型
禁用字符集轉換的配置方法
在isql環境中執行:
sp_configure “disable character set conversion”,1
go
“disable character set conversion”參數默認配置值爲0,即啓用字符集轉換。
如何配置字符集的轉換類型
把”enable unicode conversions”參數設置爲1或者2。當配置爲1時,此設置使用直接轉換或Unicode轉換;當配置爲2時,此設置使用Unicode轉換;默認配置值爲0,使用直接轉換。
在isql環境中執行:
sp_configure ”enable unicode conversions”,1
go
二、如何配置服務器端缺省字符集
直接轉換法
直接轉換法是指直接使用Sybase提供的實用程序,如UNIX平臺上使用sqlloc命令或者編輯sqlloc.rs腳本文件;Windows平臺使用“服務器配置”圖形化管理工具直接配置服務器端字符集。
使用直接轉換法的條件是:
――服務器中沒有用戶數據
――對服務器中用戶數據的損壞是可以接受的
――絕對確定服務器中的數據只使用ASCII-7字符集
間接轉換法
間接轉換法相對於直接轉換法而言,需要通過一下三步來完成配置工作:
先將服務器端的數據使用bcp命令導出
再選擇直接轉換法之中的一種方式配置服務器端字符集
再使用帶有-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平臺
“服務器配置”管理工具提供了一個易於操作的圖形化管理平臺,根據工具中提示的信息,很容易就完成了字符集的配置工作,這裏就不多講了,請參看相關文檔說明。
三、如何配置客戶端缺省字符集
配置客戶端缺省字符集實際上就是對“$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“,再決定如何修改。
四、如何設置jconnect的字符集?
可以通過設置 CHARSET 驅動程序屬性指定要在應用程序中使用的字符集。如果沒有設置 CHARSET 屬性:
·對於 com.sybase.jdbcx.SybDriver.VERSION_2,jConnect 使用 iso_1 作爲缺省字符集。
·對於 com.sybase.jdbcx.SybDriver.VERSION_3 和更高版本,jConnect 使用數據庫的缺省字符集,並進行自動調整以在客戶端執行任何必要的轉換。
設置jconnect字符集的方法:
?charset=
例如:
jdbc:sybase:Tds:hostname:5001/eas_test? jconnect_version=0&charset=cp936
下表列出了 jConnect 支持的 Sybase 字符集。表中還列出了每個支持的字符集的對應的 JDK 字節轉換程序。
雖然 jConnect 支持 UCS-2,但目前 Sybase 數據庫或 Open Server 都不支持 UCS-2。
Adaptive Server 12.5 和更高版本支持一個 Unicode 版本(稱爲 UTF-16 編碼)。
表 1:jconnect支持的 Sybase 字符集
SybCharset 名稱 |
JDK 字節轉換程序 |
ascii_7 |
ASCII |
big5 |
Big5 |
big5hk(參見注意) |
Big5_HKSCS |
cp037 |
Cp037 |
cp437 |
Cp437 |
cp500 |
Cp500 |
cp850 |
Cp850 |
cp852 |
Cp852 |
cp855 |
Cp855 |
cp857 |
Cp857 |
cp860 |
Cp860 |
cp863 |
Cp863 |
cp864 |
Cp864 |
cp866 |
Cp866 |
cp869 |
Cp869 |
cp874 |
Cp874 |
cp932 |
MS932 |
cp936 |
GBK |
cp950 |
Cp950 |
cp1250 |
Cp1250 |
cp1251 |
Cp1251 |
cp1252 |
Cp1252 |
cp1253 |
Cp1253 |
cp1254 |
Cp1254 |
cp1255 |
Cp1255 |
cp1256 |
Cp1256 |
cp1257 |
Cp1257 |
cp1258 |
Cp1258 |
deckanji |
EUC_JP |
eucgb |
EUC_CN |
eucjis |
EUC_JP |
eucksc |
EUC_KR |
ibm420 |
Cp420 |
ibm918 |
Cp918 |
iso_1 |
ISO8859_1 |
iso88592 |
ISO8859-2 |
is088595 |
ISO8859_5 |
iso88596 |
ISO8859_6 |
iso88597 |
ISO8859_7 |
iso88598 |
ISO8859_8 |
iso88599 |
ISO8859_9 |
iso15 |
ISO8859_15_FDIS |
koi8 |
KOI8_R |
mac |
Macroman |
mac_cyr |
MacCyrillic |
mac_ee |
MacCentralEurope |
macgreek |
MacGreek |
macturk |
MacTurkish |
sjis |
MS932 |
tis620 |
MS874 |
utf8 |
UTF8 |
注意: 只有在使用 JDK 1.3 或更高版本時才支持 big5hk 字符集。
3.如何選擇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進行的擴展,第一字節爲0x81~0xFE,第二字節分兩部分,一是0x40~0x7E,二是0x80~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%的空間用來存儲。
一般來說,由於EUCGB不支持國標一、二級字庫以外的漢字,所以我們推薦用戶在服務器端和客戶端都使用CP936字符集,或者在ASE 12.5.0.3之後還可以使用GB18030字符集,它可以支持一些比較生僻的漢字。它的不足是隻有一種排序方式,即區分大小寫的Binary方式。所以,如果需要使用支持中文字符集且不區分大小寫的數據庫時,就只能使用UTF-8作爲服務器端字符集,而客戶端使用CP936或GB18030字符集。
另外,還有一種選擇是,服務器端和客戶端都使用iso_1字符集,雖然iso_1字符集並不直接支持中文字符,但我們將服務器端和客戶端都設置成iso_1字符集後,系統也不會在客戶端和服務器端進行字符轉換,它只不過將一個漢字的兩個字節當做兩個單獨字符來處理,一般情況下沒有問題。但當執行like匹配查詢的時候,它有可能返回不正確的結果,原因是服務器端是根據單字節去匹配查詢條件的,很可能會有前一個漢字的第二字節與後一個漢字的第一字節的內碼組合符合查詢條件,被服務器端作爲查詢結果返回來。
如果客戶端是通過JDBC訪問數據庫的,那麼,爲了支持中文字符,服務器端最好採用CP936/GB18030或UTF-8作爲字符集。如果應用是多層結構的,那麼應用服務器的字符集也最好採用與數據庫服務器端相同的字符集。
4.如何查看服務器端、客戶端字符集
查看服務器端字符集:
在isql環境中執行:
sp_helpsort
go
查看客戶端字符集:
在isql環境中執行:
select @@client_csname
go
5.錯誤處理
爲什麼會出現字符集轉換失敗?
當字符存在於客戶端字符集中但在服務器字符集中不存在時,Adaptive Server的字符集轉換將報告轉換錯誤,反之亦然。
用戶會碰到下面的錯誤消息:
Msg 2402,Severity 16 (EX_USER):
Error converting client characters into server's character set. Some character(s) could not be converted.
轉換錯誤會阻止插入與更新語句的執行。如果發生此情況,請檢查數據中有問題的字符並替換它們。
當客戶端發送數據時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 (`?')。
當在客戶端查詢服務器端存儲的數據時,當碰到中文漢字,在客戶端顯示亂碼的現象,且沒有任何提示信息。
這是我們在應用中經常會碰到的現象,產生的原因是:客戶端與服務器端字符集不符。怎麼解釋呢?假設我們先期設置服務器端字符集爲iso_1,客戶端字符集也爲iso_1,然後我們從客戶端向服務器端錄入了所有的數據;之後當我們需要查詢時,使用的客戶端,它的字符集爲cp850,那麼勢必在該客戶端上顯示的字符集爲亂碼。
當出現這種情況時,最好配置客戶端字符集爲先期客戶端使用的字符集或者配置客戶端字符集與服務器端字符集一致,使得客戶端字符集與服務器端字符集匹配。這裏我們不建議用戶修改服務器端字符集,因爲服務器中此時已經存在大量的數據,在使用直接轉換方式時,由於源字符集與目的字符集中可能存在無法轉換的字符而導致Adaptive Server無法啓動;如果使用間接的轉換方式,會增加工作量。
bcp in結果中文亂碼問題
1)現象
bcp in後,server顯示中文亂碼
2)原因
客戶端平臺缺省字符集與客戶端Open client所使用字符集不一致造成的
3)解決方案/注意事項
A、 將客戶端字符集改成與server端一致,加-J但不附加客戶端字符集
B、 或,加-J參數並附加客戶端字符集,來請求服務器進行字符集轉換。
6. 附:如何安裝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會自動宕掉,需要第二次重啓後才能使用)