http://welcomyou.javaeye.com/blog/371189
JA16SJISTILDE
JAPANESE_JAPAN.JA16SJISTILDE
Oracle NLS_LANG小結
關鍵字: oracle nls_lang character set 字元集 從客戶那裡拿到一個資料庫,客戶的資料庫Server的字元集是JA16SJIS,使用export的Client端的NLS_LANG是 US7ASCII。問過DBA,得到的結論是由於Client使用的字元集是Server字元集的子集,所以匯出的dump檔案應該無效,以前也看過一本 《循序漸進Oracle》,從那本書的說的情況看也應該是有問題的。但是自己還是試了試,報了很多錯“長度不夠”,原因是我的Oracle Instance字元集是AL32UTF8,沒辦法重建立了個JA16SJIS資料庫,Console的NLS_LANG設定為 AMERICAN_AMERICA.US7ASCII,成功匯入。表中的日文字元都沒有問題。
很奇怪為什麼能成功匯入,做了個是實驗:
建立了一個Test表,包含日文字元。
匯出兩次,NLS_LANG分別是AMERICAN_AMERICA.US7ASCII和AMERICAN_AMERICA.JA16SJIS, 對比兩次匯出的dump檔案,發現只有檔案頭不一樣,其餘部分基本一致,尤其是建表和插入的資料二進位部分完全一樣。NLS_LANG的設定可能不會影響 dump檔案的編碼。通過查詢Oracle網站得到這樣的一句話
In Oracle9i the Export utility always exports user data, including Unicode data, in the character set of the database. The Import utility automatically converts the data to the character set of the target database.
也就是說,dump檔案的資料的編碼和來源資料庫的相同,不管Client的NLS_LANG如何設定。如果來源資料庫的字元集和目標資料庫的字元集 不一致,import時會自動轉換。當然在不一致的情況下,來源資料庫的字元集一定要是目標資料庫的子集。再查了下《循序漸進Oracle》,書中關於匯入 匯出的例子使用的Oracle 8i,應該是作者偷懶把上一版的內容直接拿過來沒更新。
另外再Oracle提供的關於NLS_LANG FAQ也列出了幾條對NLS_LANG誤解:
“NLS_LANG和資料庫的字元集一樣或許是正確的,但是經常是不對的。不要認為NLS_LANG必須和資料庫的字元集一樣,這經常是錯的。” 《循序漸進Oracle》中說NLS_LANG一樣的話可以提高效能,因為不需要字元集的轉換。其實這樣的轉換不時發生在Server端,Client端 轉換完成後傳遞給Server端。我覺得,只要NLS_LANG是Server的字元集的子集就可以。
“NLS_LANG的字元集設定不會更改Client端的字元集。它只是用來告訴Oracle你在Client端使用什麼字元集,你不能通過設定NLS_LANG去影響Client的字元集”。而且如果Client端的字元集和NLS_LANG不相容,會導致資料庫亂碼。
“如果你不在Client端設定NLS_LANG,那麼預設會使用Server的NLS_LANG設定,這是錯的。如果Oracle在安裝時沒有 設定NLS_LANG,那麼NLS_LANG不會另外再設定,而是使用預設值:AMERICAN_AMERICA.US7ASCII。語言是 AMERICAN,地區是AMERICA,字元集US7ASCII”
“設定NLS_LANG的LANGUAGE 和 TERRITORY部分不會影響儲存在資料庫的字元。將NLS_LANG設定為JAPANESE_JAPAN.WE8MSWIN1252不會允許你儲存日 文。因為WE8MSWIN1252字元集不支援日文。但是設定成AMERICAN_AMERICA.JA16SJIS會允許你儲存日文,假設你輸入的字元 是JA16SJIS,並且資料庫的字元集也支援日文(如UTF8或者JA16SJIS)”
還需要注意的是:
SELECT USERENV ('language') FROM DUAL返回的是Session的LANGUAGE和 TERRITORY資料庫的字元集。
參考:http://www.oracle.com/technology/tech/globalization/htdocs/nls_lang%20faq.htm