概述: 本地化是系統(tǒng)或軟件運(yùn)行的語(yǔ)言和文化環(huán)境。設(shè)置NLS_LANG環(huán)境參數(shù)是規(guī)定Oracle數(shù)據(jù)庫(kù)軟件本地化行為最簡(jiǎn)單的方式。
NLS_LANG參數(shù)不但指定了客戶(hù)端應(yīng)用程序和Oracle數(shù)據(jù)庫(kù)所使用的語(yǔ)言和地區(qū);同時(shí)也指定了客戶(hù)端程序輸入數(shù)據(jù)和顯示數(shù)據(jù)所使用的字符集。
本文主要包含如下五部分 ◆
NLS_LANG環(huán)境變量的構(gòu)成 ◆ NLS_LANG環(huán)境變量的格式 ◆
如何查看數(shù)據(jù)庫(kù)NLS參數(shù)設(shè)置 ◆ 舉例說(shuō)明如何設(shè)置NLS_LANG環(huán)境變量 ◆
舉例說(shuō)明一些特殊情況
一,NLS_LANG環(huán)境變量的構(gòu)成 NLS_LANG環(huán)境變量由如下三部分構(gòu)成: 1,LANGUAGE:客戶(hù)端系統(tǒng)所使用的語(yǔ)言。
指定Oracle數(shù)據(jù)庫(kù)反饋的消息(例如異常信息,提示信息等)、字符數(shù)據(jù)的排列順序(當(dāng)指定ORDER BY時(shí))、日(年月日中的天)名稱(chēng),月名稱(chēng)等所使用的語(yǔ)言。
每個(gè)支持的語(yǔ)言都有唯一的名稱(chēng)。例如,若操作系統(tǒng)使用簡(jiǎn)體中文,則為SIMPLIFIED CHINESE;若操作系統(tǒng)使用美式英文操作系統(tǒng),則為AMERICAN。
LANGUAGE參數(shù)中隱含地區(qū)和字符集參數(shù)的信息。如果沒(méi)有指定LANGUAGE參數(shù)的值,則默認(rèn)值為AMERICAN。 2,TERRITORY:客戶(hù)端系統(tǒng)所在的地區(qū)。
指定默認(rèn)的日期,貨幣以及數(shù)字格式。 每一個(gè)支持的地區(qū)都有唯一的名稱(chēng)。如,CHINA,AMERICA或CANADA。 如果沒(méi)有指定TERRITORY參數(shù),則此參數(shù)的值由LANGUAGE參數(shù)推理得出。 3,CHARSET:客戶(hù)端應(yīng)用程序所使用的字符集。 正確地設(shè)置NLS_LANG環(huán)境變量,則使得字符數(shù)據(jù)能夠在客戶(hù)端字符集和數(shù)據(jù)庫(kù)字符集之間正確地轉(zhuǎn)換。
設(shè)置NLS_LANG不會(huì)改變客戶(hù)端系統(tǒng)的字符集,它僅僅是讓Oracle數(shù)據(jù)庫(kù)知道客戶(hù)端應(yīng)用程序使用的是什么字符集,從而進(jìn)行相應(yīng)的字符集轉(zhuǎn)換。 如果客戶(hù)端和數(shù)據(jù)庫(kù)字符集相同,則Oracle數(shù)據(jù)庫(kù)忽略字符集校驗(yàn),不執(zhí)行字符集轉(zhuǎn)換。
Oracle所支持的每個(gè)字符集都有唯一的縮寫(xiě)。如,ZHS16GBK(GBK),AL32UTF8(UTF-8)等。 每一個(gè)LANGUAGE默認(rèn)都有一個(gè)和它關(guān)聯(lián)的字符集。
二,NLS_LANG環(huán)境變量的格式 NLS_LANG = LANGEAGE_TERRITORY.CHARSET 注意,此處的.為英文逗號(hào)。
三,如何查看數(shù)據(jù)庫(kù)NLS參數(shù)設(shè)置 1,通過(guò)NLS_DATABASE_PARAMETERS視圖查看數(shù)據(jù)庫(kù)的NLS參數(shù)。 SELECT
* FROM NLS_DATABASE_PARAMETERS ORDER BY PARAMETER; 查詢(xún)?nèi)缦聢D所示。其中,NLS_CHARACTERSET參數(shù)的值就表示數(shù)據(jù)庫(kù)所使用的字符集(創(chuàng)建數(shù)據(jù)庫(kù)時(shí)所指定的字符集)。
2,通過(guò)NLS_SESSION_PARAMETERS視圖查看當(dāng)前用戶(hù)會(huì)話(huà)的NLS參數(shù)。 SELECT * FROM NLS_SESSION_PARAMETERS ORDER
BY PARAMETER; 查詢(xún)?nèi)缦聢D所示:
四,舉例說(shuō)明如何設(shè)置NLS_LANG環(huán)境變量 此部分主要通過(guò)Oracle數(shù)據(jù)庫(kù)自帶的SQL PLUS數(shù)據(jù)庫(kù)客戶(hù)端程序說(shuō)明如何設(shè)置NLS_LANG中的字符集。 實(shí)驗(yàn)環(huán)境: 數(shù)據(jù)庫(kù)NLS參數(shù)設(shè)置:數(shù)據(jù)庫(kù)NLS參數(shù)設(shè)置如第三部分(查看數(shù)據(jù)庫(kù)NLS參數(shù)設(shè)置)中第一個(gè)圖所示,NLS_CHARACTERSET=AL32UTF8。 操作系統(tǒng):Windows
10英文企業(yè)版64位。 實(shí)驗(yàn)準(zhǔn)備: 1,創(chuàng)建一個(gè)表CHINESE_DATA
CREATE TABLE CHINESE_DATA(
CH_DATA VARCHAR2(64)
);
實(shí)驗(yàn)一: 此實(shí)驗(yàn)舉例說(shuō)明如何正確地設(shè)置命令行窗口和系統(tǒng)的NLS_LANG環(huán)境變量,從而能夠正確地顯示查詢(xún)結(jié)果。
1,設(shè)置客戶(hù)端系統(tǒng)的NLS_LANG環(huán)境變量  如上圖所示,Windows系統(tǒng)環(huán)NLS_LANG境變量的值為AMERICAN_AMERICA.ZHS16GBK,而數(shù)據(jù)庫(kù)的字符集為AL32UTF8。 很顯然,數(shù)據(jù)庫(kù)字符集和客戶(hù)端NLS_LANG中的字符集不一樣。這就有可能導(dǎo)致客戶(hù)端查詢(xún)數(shù)據(jù)時(shí)出現(xiàn)亂碼。
2,插入一條數(shù)據(jù)
INSERT INTO CHINESE_DATA VALUES('漢字');
COMMIT;
注意:插入數(shù)據(jù)時(shí)可以借助PL/SQL Developer等工具,以確保數(shù)據(jù)能正確地輸入并存儲(chǔ)到數(shù)據(jù)庫(kù)中。 3,使用默認(rèn)環(huán)境,在不改變命令行窗口代碼頁(yè)(每個(gè)代碼頁(yè)都對(duì)應(yīng)著一個(gè)字符集)的情況下查詢(xún)數(shù)據(jù)。
437代碼頁(yè)對(duì)應(yīng)的字符集主要包含拉丁字母。
437代碼頁(yè)所包含的字符分類(lèi):
如上圖所示,不出所料,查詢(xún)結(jié)果出現(xiàn)亂碼。
實(shí)驗(yàn)說(shuō)明:
數(shù)據(jù)庫(kù)字符集為AL32UTF8,Oracle通過(guò)NLS_LANG得知客戶(hù)端字符集為ZHS16GBK。
Oracle在返回查詢(xún)結(jié)果時(shí),把數(shù)據(jù)轉(zhuǎn)換為GBK格式,而437代碼頁(yè)所包含的字符中根本沒(méi)有漢字字符,所以顯示為亂碼。 4,把命令行窗口的代碼頁(yè)改為65001,其對(duì)應(yīng)的字符集為UTF-8。

如上圖所示,查詢(xún)結(jié)果為不可見(jiàn)字符,也屬于亂碼。
實(shí)驗(yàn)說(shuō)明:
Oracle返回的數(shù)據(jù)為GBK字符集,而控制臺(tái)為UTF-8字符集。盡管UTF-8字符集是GBK字符集的超集(其包含了所有GBK字符集中的字符),
但是兩者對(duì)同一個(gè)字符的編碼是不一樣的。如圖所示,GBK中“漢字”這兩個(gè)字符所包含的字節(jié)(Bytes)在UTF-8字符集中都表示不可見(jiàn)字符。
所以,其顯示結(jié)果是不正確的。 5,把控制臺(tái)代碼頁(yè)設(shè)置為936,其對(duì)應(yīng)的字符集為GB2312。
注意,由于本次實(shí)驗(yàn)的環(huán)境為英文系統(tǒng),故而需要設(shè)置命令行窗口的字體。不然,無(wú)法正確顯示中文字符。

如圖所示,其查詢(xún)結(jié)果是正確的。
實(shí)驗(yàn)說(shuō)明:
盡管GBK字符集是GB2312字符集的超集,其比GB2312字符集包含更多的字符。
但是GBK字符集向前兼容GB2312字符集?!皾h字”這兩個(gè)字符在GBK和GB2312字符集中的編碼完全相同,所以查詢(xún)能夠正確顯示。
實(shí)驗(yàn)結(jié)論:
1,NLS_LANG環(huán)境變量中所指定的字符集其實(shí)就是數(shù)據(jù)庫(kù)客戶(hù)端應(yīng)用程序所使用的字符集。
如果客戶(hù)端應(yīng)用程序不支持NLS_LANG中所包含的字符集或者所支持的字符集與NLS_LANG中的字符集不兼容,則會(huì)出現(xiàn)亂碼。
2,此外,即使客戶(hù)端字符集和數(shù)據(jù)庫(kù)字符集相同,也可能會(huì)出現(xiàn)亂碼。
假如,Oracle數(shù)據(jù)庫(kù)為AL32UTF8字符集,客戶(hù)端使用UTF-8字符集。
然而,現(xiàn)實(shí)情況總是很復(fù)雜的。如果客戶(hù)端和數(shù)據(jù)庫(kù)所支持的UNICODE標(biāo)準(zhǔn)不一樣,則在很罕見(jiàn)的情況下仍有可能出現(xiàn)亂碼。
實(shí)驗(yàn)二: 此實(shí)驗(yàn)舉例說(shuō)明數(shù)據(jù)庫(kù)不支持客戶(hù)端字符集所包含的字符時(shí)會(huì)產(chǎn)生什么樣的結(jié)果。 1,創(chuàng)建一個(gè)使用WE8MSWIN1252字符集的數(shù)據(jù)庫(kù)。 本次實(shí)驗(yàn)創(chuàng)建了一個(gè)名為TALRASHA的數(shù)據(jù)庫(kù),其使用WE8MSWIN1252字符集。 以下是通過(guò)NLS_DATABASE_PARAMETERS視圖所查詢(xún)到的數(shù)據(jù)庫(kù)NLS參數(shù)。
2,設(shè)置客戶(hù)端系統(tǒng)的NLS_LANG環(huán)境變量
3,插入并查詢(xún)數(shù)據(jù) 由于需要存儲(chǔ)中文字符,故此處將代碼頁(yè)設(shè)置為936。
 實(shí)驗(yàn)說(shuō)明: 如上圖所示,由于數(shù)據(jù)庫(kù)字符集為WE8MSWIN1252,其不能正確地存儲(chǔ)中文字符,但可以正確存儲(chǔ)英文字符。 所以,查詢(xún)結(jié)果中,中文為亂碼,英文正常顯示。
實(shí)驗(yàn)結(jié)論: 1,如果客戶(hù)端應(yīng)用程序所使用的字符集是數(shù)據(jù)庫(kù)字符集的超集,或者客戶(hù)端應(yīng)用程序中的某些字符不在數(shù)據(jù)庫(kù)字符集所表示的范圍之內(nèi),則數(shù)據(jù)庫(kù)在進(jìn)行字符集轉(zhuǎn)換時(shí)會(huì)產(chǎn)生錯(cuò)誤的結(jié)果。
2,屬于客戶(hù)端字符集和數(shù)據(jù)庫(kù)字符集交集中的字符能夠正常存儲(chǔ)和顯示。
最終結(jié)論: 1,在查詢(xún)數(shù)據(jù)時(shí),客戶(hù)端字符集應(yīng)該等于數(shù)據(jù)庫(kù)字符集或者是數(shù)據(jù)庫(kù)字符集的超集。從而避免顯示結(jié)果出現(xiàn)亂碼的問(wèn)題。
2,在數(shù)據(jù)輸入時(shí),客戶(hù)端字符集應(yīng)該等于數(shù)據(jù)庫(kù)字符集或者是數(shù)據(jù)庫(kù)字符集的子集。從而使得輸入字符能夠在數(shù)據(jù)庫(kù)中正確地保存。 3,在創(chuàng)建數(shù)據(jù)庫(kù)時(shí),盡可能使用UNICODE字符集,從而避免字符數(shù)據(jù)不能正確存儲(chǔ)的問(wèn)題。
五,舉例說(shuō)明一些特殊情況 通過(guò)以上兩個(gè)實(shí)驗(yàn)基本說(shuō)明了客戶(hù)端應(yīng)用程序字符集,客戶(hù)端系統(tǒng)的NLS_LANG所包含的字符集和Oracle數(shù)據(jù)庫(kù)字符集三者之間的關(guān)系。 但是,某些數(shù)據(jù)庫(kù)客戶(hù)端應(yīng)用程序有自己獨(dú)立的客戶(hù)端環(huán)境配置,其不依賴(lài)于客戶(hù)端系統(tǒng)中的NLS環(huán)境變量或者依僅賴(lài)于某些系統(tǒng)環(huán)境變量。 例如,PL/SQL Developer和SQL Developer。它們的編輯器有自己的字符集和字體的設(shè)置,同時(shí)這兩個(gè)軟件也支持一些其他設(shè)置(如日期格式或者地區(qū)等)。 所以,在進(jìn)行第四部分的試驗(yàn)一時(shí),建議先通過(guò)這兩個(gè)應(yīng)用程序插入數(shù)據(jù)。 此外,還需要注意字體對(duì)數(shù)據(jù)顯示的影響。有的字體不能正確地顯示輸入或查詢(xún)結(jié)果中的字符也會(huì)產(chǎn)生問(wèn)題。
|