4.1使用客戶端sqlplus向數據庫存儲數據
這個過程存在3個字符集設置
(1)客戶端應用字符集
(2)客戶端NLS_LANG參數設置
(3)服務器端數據庫字符集(Character Set)設置
客戶端應用sqlplus中能夠顯示什么樣的字符取決于客戶端操作系統語言環境(客戶端應用字符集),但在應用中錄入這些字符后,這些字符能否在數據庫中正常存儲,還與另外兩個字符集設置緊密相關,其中客戶端NLS_LANG參數主要用于字符數據傳輸過程中的轉換判斷。常見的亂碼大致有兩種情形:
(1)漢字變成問號“?”;
當從字符集A 轉換成字符集B時,如果轉換字符之間不存在對應關系,NLS_LANG使用替代字符“?”替代無法映射的字符
(2)漢字變成未知字符(雖然有些是漢字,但與原字符含義不同)
轉換存在對應關系,但字符集A 中的字符編碼與字符集B 中的字符編碼代表不同含義
4.2發生亂碼原因
亂碼產生是由于幾個字符集之間轉換不匹配造成,分以下幾種情況:
(注:字符集之間如果不存在子集、超集對應關系時的情況不予考慮,因為這種情況下字符集之間轉換必產生亂碼)
1)服務器端數據庫字符集與客戶端應用字符集相同,與客戶端NLS_LANG參數設置不同
如果客戶端NLS_LANG字符集是其它兩種字符集的子集,轉換過程將出現亂碼。
解決方法:將三種字符集設置成同一字符集,或NLS_LANG字符集是其它兩種字符集的超集
2)服務器端數據庫字符集與客戶端NLS_LANG參數設置相同,與客戶端應用字符集不同
如果客戶端應用字符集是其它兩種字符集的超集時,轉換過程將出現亂碼,但對于單字節編碼存儲中文問題,可參看本文第5章節的分析
3)客戶端應用字符集、客戶端NLS_LANG參數設置、服務器端數據庫字符集互不相同
此種情況較為復雜,但三種字符集之間只要有不能轉換的字符,則必產生亂碼
4.3導入/導出過程出現亂碼原因
這個過程存在4個字符集設置,在3.1章節中已分析
(1)源數據庫字符集
(2)EXP過程中NLS_LANG參數
(3)IMP過程中NLS_LANG參數
(4)目標數據庫字符集
出現亂碼原因
1)當源數據庫字符集不等于EXP過程中NLS_LANG參數,且源數據庫字符集是EXP過程中NLS_LANG的子集,才能保證導出文件正確,其他情況則導出文件字符亂碼
2)EXP過程中NLS_LANG字符集不等于IMP過程中NLS_LANG字符集,且EXP過程中NLS_LANG字符集是IMP過程中NLS_LANG字符集的子級, 才能保證第一次轉換正常,否則第一次轉換中出現亂碼。
3)如果第一次轉換正常,IMP過程中NLS_LANG字符集是目標數據庫字符集的子集或相同,才能保證第二次轉換正常,否則則第二次轉換中出現亂碼
五.單字節編碼存儲中文問題
由于歷史的原因,早期的oracle沒有中文字符集(如oracle6、oracle7、oracle7.1),但有的用戶從那時起就使用數據庫了,并用US7ASCII字符集存儲了中文,或是有的用戶在創建數據庫時,不考慮清楚,隨意選擇一個默認的字符集,如WE8ISO8859P1或US7ASCII,而這兩個字符集都沒有漢字編碼,雖然有些時候選用這種字符集好象也能正常使用,但用這種字符集存儲漢字信息從原則上說就是錯誤的,它會給數據庫的使用與維護帶來一系列的麻煩。
正常情況下,要將漢字存入數據庫,數據庫字符集必須支持中文,而將數據庫字符集設置為US7ASCII等單字節字符集是不合適的。US7ASCII字符集只定義了128個符號,并不支持漢字。另外,如果在SQL*PLUS中能夠輸入中文,操作系統缺省應該是支持中文的,但如果在NLS_LANG中的字符集設置為US7ASCII,顯然也是不正確的,它沒有反映客戶端的實際情況。但在實際應用中漢字顯示卻是正確的,這主要是因為Oracle檢查數據庫與客戶端的字符集設置是同樣的,那么數據在客戶與數據庫之間的存取過程中將不發生任何轉換,但是這實際上導致了數據庫標識的字符集與實際存入的內容是不相符的。而在SELECT的過程中,Oracle同樣檢查發現數據庫與客戶端的字符集設置是相同的,所以它也將存入的內容原封不動地傳送到客戶端,而客戶端操作系統識別出這是漢字編碼所以能夠正確顯示。
在這個例子中,數據庫與客戶端都沒有設置成中文字符集,但卻能正常顯示中文,從應用的角度看好象沒問題。然而這里面卻存在著極大的隱患,比如在應用length或substr等字符串函數時,就可能得到意外的結果。
對于早期使用US7ASCII字符集數據庫的數據遷移到oracle8i/9i中(使用zhs16gbk),由于原始數據已經按照US7ASCII格式存儲,對于這種情況,可以通過使用Oracle8i的導出工具,設置導出字符集為US7ASCII,導出后使用UltraEdit等工具打開dmp文件,修改第二、三字符,修改 0001 為0354,這樣就可以將US7ASCII字符集的數據正確導入到ZHS16GBK的數據庫中。
六.結束語
為了避免在數據庫遷移過程中由于字符集不同導致的數據損失,oracle提供了字符集掃描工具(character set scanner),通過這個工具我們可以測試在數據遷移過程中由于字符集轉換可能帶來的問題,然后根據測試結果,確定數據遷移過程中最佳字符集解決方案。
原文轉自:http://blogread.cn/it/article/4654