■ 遼寧 彭碩
某公司正在使用BF品牌的ERP系統(tǒng),其中系統(tǒng)后端數(shù)據(jù)庫為Sybase ASE 12.5.4,運(yùn)行于中文版Windows Server 2008 R2操作系統(tǒng)上。ERP客戶端程序均運(yùn)行于中文版Windows操作系統(tǒng)上,在ERP客戶端程序內(nèi)顯示、錄入中文字符均正常。
當(dāng)在使用Sybase Central v6.0等軟件連接數(shù)據(jù)庫時(shí),數(shù)據(jù)庫中存儲的(包括用戶表中的數(shù)據(jù)、存儲過程和觸發(fā)器)中文字符在軟件內(nèi)顯示為亂碼,給數(shù)據(jù)分析、排錯(cuò)等工作造成不便,如圖1所示。
通過調(diào)查,確定實(shí)際情況如下:ERP軟件廠商在進(jìn)行部署之初,即將Sybase數(shù)據(jù)庫字符集設(shè)置為“cp850”,數(shù)據(jù)庫語言設(shè)置為“us_english”。且在長達(dá)數(shù)年的實(shí)際使用中,并未有ERP系統(tǒng)的最終用戶反應(yīng)中文存在亂碼的問題。
圖1 Sybase Central查詢結(jié)果中顯示亂碼
為進(jìn)一步確定數(shù)據(jù)庫中的中文字符以何種編碼形式存儲,筆者使用Wireshark軟件對Sybase Central的查詢過程進(jìn)行抓包。通過分析數(shù)據(jù)包的載荷,可發(fā)現(xiàn)常見漢字均以雙字節(jié)形式存儲。(受限于測試條件,未能在數(shù)據(jù)庫中找到特別生僻的漢字——即GB18030編碼中存在的少量占四字節(jié)存儲空間的漢字。)例如,“劉”字在數(shù)據(jù)包中的十六進(jìn)制形態(tài)為“C1F5”,這與現(xiàn)行的三種簡體中文編碼(GB2312、GBK、GB18030)相對應(yīng)。
由于在本案例中的Sybase ASE處于生產(chǎn)環(huán)境,為避免對ERP系統(tǒng)運(yùn)行造成影響,或出現(xiàn)不可預(yù)知的兼容性問題,因此不可能對Sybase ASE數(shù)據(jù)庫的字符集進(jìn)行修改。
綜上所述,盡管CP850(西歐)字符集并不適合存儲中文字符,但其并未改變中文字符的雙字節(jié)編碼結(jié)構(gòu)。通過抓包亦可證實(shí),Sybase Central等軟件已經(jīng)收到了漢字正確的二進(jìn)制代碼,但卻無法將其解碼為漢字。由此可推斷,是這些軟件的字符集設(shè)置出現(xiàn)了問題。
在Sybase ASE 12.5.0.3及更高的版本中,共支持4種可顯示簡體中文的字符集(編 碼),分別是EUCGB、CP936、GB18030和UTF8。EUCGB字符集源自GB2312標(biāo)準(zhǔn),僅支持漢字6000余個(gè);CP936字符集源自GBK標(biāo)準(zhǔn),支持漢字20000余個(gè),并向下兼容GB2312;GB18030字符集源自同名標(biāo)準(zhǔn),為我國目前最新的中文編碼字符集強(qiáng)制性標(biāo)準(zhǔn),向下兼容GBK和GB2312。因UTF8的編碼規(guī)則與前述三種字符集互不兼容,故不在本案例中探討。
在Windows系統(tǒng)的區(qū)域和語言設(shè)置中,有一處“非Unicode程序的語言”設(shè)置。例如,使用記事本編輯一段中文,在保存時(shí)選擇“ANSI”編碼,再將前述設(shè)置調(diào)整為“英語(美國)”。重啟計(jì)算機(jī)后,無論是在命令行還是記事本中,均無法正確查看文件中的漢字。盡管文件中的數(shù)據(jù)沒有變(可通過WinHEX驗(yàn)證),但由于字符集設(shè)置不同,顯示結(jié)果也不同。
圖2 客戶端的locales.dat文件原配置
圖3 修改后的配置
圖4 客戶端的locales.dat文件原配置
在簡體中文版本的Windows操作系統(tǒng)上,通過在命令行中輸入命令“chcp”,即可得知系統(tǒng)的“中文(中國)”區(qū)域設(shè)置,對應(yīng)的頁碼(字符集)為936(GBK)。因此,在本案例中,筆者選用CP936作為Sybase開放客戶端(Open Client)的字符集,以獲得更好的兼容性。
在Sybase安裝目錄下的locales子目錄中,有一文件名為locales.dat。據(jù)官方文檔的描述,該文件“以Sybase專有格式提供了特定平臺的語言環(huán)境信息(locale information)”,“開放客戶端(Open Client)應(yīng)用程序使用它確定要加載的本地化信息?!笨梢?,locales.dat文件是客戶端程序的語言環(huán)境和字符集配置文件,通過對它進(jìn)行修改,應(yīng)當(dāng)可以修正中文亂碼的問題。
該文件中,依服務(wù)器端操作系統(tǒng)平臺的不同,將配置分成了不同的部分。其格式為:
[PLATFORM]
locale=vendor_locale,syb_language,syb_charset
提示:請?jiān)谛薷那皩ocales.dat文件進(jìn)行備份。
例如,某Sybase ASE運(yùn)行于Windows Server操作系統(tǒng)上。客戶端的locales.dat文件原配置如圖2所示。
其中最后一行中的“default”,即為針對該平臺的默認(rèn)語言和字符集配置。我們對它進(jìn)行修改即可。修改后的配置如圖3所示。
在Linux平臺上,為管理操作系統(tǒng)的語言環(huán)境,可能會(huì)存在“$LANG”變量。該變量對于運(yùn)行在Linux平臺上的Sybase ASE同樣具有意義。(在其他操作系統(tǒng)平臺上亦可能存在“LANG”變量,需要注意識別。)
例 如,某Sybase ASE運(yùn)行于RHEL 6操作系統(tǒng)上,RHEL 6系統(tǒng)具有變量“$LANG=en_US.UTF-8”??蛻舳说膌ocales.dat文件原配置如圖4所示。
這種情況下,直接修改默認(rèn)值(default)并無效果,需要根據(jù)“$LANG”變量的值進(jìn)行有針對性的修改。修改后的配置如圖5所示。
在完成修改后,需重啟Sybase Central。而 在當(dāng)建立“連接”時(shí),點(diǎn)擊“選項(xiàng)(Details)”按 鈕,在“字符 集(Character Set)”中選 擇“cp936”(與locales.dat中的修改相對應(yīng)),在“語言(Language)”中選擇“us_english”(與Sybase ASE安裝語言相對應(yīng)),如圖6所示。
對于Sybase ASE 15.0及更高版本的服務(wù)器,還需要修改一處配置,以禁用Unicode轉(zhuǎn)換。
對于15.0之前版本的Sybase ASE,此配置默認(rèn)值為0,無需修改。
圖5 根據(jù)“$LANG”修改后的配置
圖6 Sybase Central v6.0中設(shè)置連接
完成上述配置后,再使用Sybase Central瀏覽數(shù)據(jù)庫中的內(nèi)容,即可發(fā)現(xiàn)中文字符已經(jīng)可以正常顯示了。
同時(shí),在SQL Advantage(或Interactive SQL)、iSQL等工具中使用中文字符進(jìn)行查詢,亦可得到正確的查詢結(jié)果。
圖7 使用iSQL等工具連接數(shù)據(jù)庫出現(xiàn)錯(cuò)誤消息
在本案例中,Sybase ASE上僅安裝了“english”語言。如在連接設(shè)置中選擇其他語言(如“Chinese”),會(huì)得到“Neither language name in login record 'chinese'nor language name in syslogins '
如使用iSQL等工具連接數(shù)據(jù)庫,會(huì)得到如圖7所示錯(cuò)誤消息。
該錯(cuò)誤消息指出,無法在客戶端的“cp936”和服務(wù)器的“cp850”字符集之間進(jìn)行轉(zhuǎn)換。但在本案例中,中文字符在數(shù)據(jù)庫中已使用雙字節(jié)格式存儲(cp936字符集與之兼容),不進(jìn)行任何字符集轉(zhuǎn)換操作,恰恰是我們所期望的結(jié)果。