【原創】Oracle管理專題之:Oracle9i 字符集與NLS_LANG搭配測試兼亂碼問題分析

【背景介紹】
===================================================================
最近在使用Oracle9i數據庫進行數據插入、查詢、導入/出,有時會出現亂碼的狀況,具體的情形有如下兩種:

1.首次插入/顯示亂碼

2.首次插入/顯示正常、但把數據用工具導出爲本地文件(例如TXT)文件,再在另外一個客戶端中打開該文件並執行時再次插入的數據顯示爲亂碼。

遂在本地建立兩個數據庫,一個爲AL32UTF8字符集,一個爲ZHS16GBK字符集,配合客戶端NLS_LANG的不一樣設置,測試亂碼的狀況及進行緣由分析。    
===================================================================

【測試目的】
===================================================================
測試不一樣的數據庫字符集和客戶端NLS_LANG搭配下,中文字符/中文日期的插入、顯示
===================================================================

【測試環境】
===================================================================
Windows 2000 Professional (英文版) + Oracle 9.2.0.1.0 + SQL*Plus: Release 9.2.0.1.0

注:這次測試的客戶端應用工具爲SQL*PLUS,若是是使用TOAD、PL/SQL Develop之類工具,獲得的結果會和如下有些不一樣。推薦使用SQL*PLUS做爲一切客戶端應用的測試工具
===================================================================

【測試數據庫】
===================================================================
本機數據庫1: SID: PAULLIN 登錄參數: qprod/qprod@paullin
本機數據庫2:SID: PAUL    登錄參數:qlinpen/pengpenglin@paul
===================================================================

【測試字符集】
===================================================================
客戶端應用/操做系統字符集:GB2312

客戶端NLS_LANG設置:
  AMERICAN_AMERICA.US7ASCII
  AMERICAN_AMERICA.WE8MSWIN1252
  AMERICAN_AMERICA.ZHS16GBK
  AMERICAN_AMERICA.AL32UTF8
  SIMPLIFIED CHINESE_CHINA.ZHS16GBK

數據庫端字符集:
  PAULLIN: AL32UF8
  PAUL: ZHS16GBK
===================================================================

【測試腳本】
===================================================================
--登錄數據庫    
     sqlplus
qprod/qprod@paullin     
     sqlplus
qlinpen/pengpenglin@paul

--執行測試腳本
     drop table test;
     drop table testdate;    

     create table test (id number(1), name varchar2(20));
     create table testdate (birthday date);  

     insert into test values(1,'Tom');
     insert into test values(2,'張三');
     insert into test values(3,'易建聯');
     commit;
    
     insert into testdate values(TO_Date( '01/08/2008 04:14:00 下午',
           'MM/DD/YYYY HH:MI:SS AM'));
     commit;
    
--查看測試結果    
     select * from test;
     select * from testdate;    
===================================================================

【測試一:數據庫端字符集爲AL32UTF8的狀況】
===================================================================
1.登錄數據庫:
  C:\Documents and Settings\qlinpen.E0015609D6309>sqlplus qprod/qprod@paullin

2.查看數據庫字符集:
  SQL> select * from nls_database_parameters where parameter = 'NLS_CHARACTERSET';    

3.測試內容及測試結果:
  1).客戶端NLS_LANG設置爲AMERICAN_AMERICA.US7ASCII:
      中文字符測試:插入/顯示中文字符均爲亂碼
      中文日期測試:ORA-01855: AM/A.M. or PM/P.M. required

  2).客戶端NLS_LANG設置爲AMERICAN_AMERICA.WE8MSWIN1252:
      中文字符測試:插入/顯示中文字符均爲正常
      中文日期測試:ORA-01855: AM/A.M. or PM/P.M. required
    
  3).客戶端NLS_LANG設置爲AMERICAN_AMERICA.ZHS16GBK:
      中文字符測試:插入/顯示中文字符均爲正常
      中文日期測試:ORA-01855: AM/A.M. or PM/P.M. required
  
  4).客戶端NLS_LANG設置爲AMERICAN_AMERICA.AL32UTF8:
      中文字符測試:插入/顯示中文字符均爲正常
      中文日期測試:ORA-01855: AM/A.M. or PM/P.M. required
    
  5).客戶端NLS_LANG設置爲SIMPLIFIED CHINESE_CHINA.ZHS16GBK:
      中文字符測試:插入/顯示中文均爲正常
      中文日期測試:插入/顯示中文日期均爲正常,格式爲DD-MM-YY(例如:08-1月 -08)  

4.測試結論:
  從測試結果來看,當數據庫端字符集爲AL32UTF8時,可以使到中文字符被正確插入/顯示的NLS_LANG的字符集爲:  WE8MSWIN125二、ZHS16GBK、AL32UTF8。
  
  可是要使到中文格式的時間可以被正確插入,則NLS_LANG的LANGUAGE和TERRITORY設置必須爲:SIMPLIFIED_CHINESE_CHINA
===================================================================

【測試二:數據庫端字符集爲ZHS16GBK的狀況】
===================================================================
1.登錄數據庫:
  C:\Documents and Settings\qlinpen.E0015609D6309>sqlplus qlinpen/pengpenglin@paul

2.查看數據庫字符集:
  SQL> select * from nls_database_parameters where parameter = 'NLS_CHARACTERSET';    

3.測試內容及測試結果:
  1).客戶端NLS_LANG設置爲AMERICAN_AMERICA.US7ASCII:
      中文字符測試:插入/顯示中文字符均爲亂碼
      中文日期測試:ORA-01855: AM/A.M. or PM/P.M. required

  2).客戶端NLS_LANG設置爲AMERICAN_AMERICA.WE8MSWIN1252:
      中文字符測試:插入/顯示中文字符均爲亂碼
      中文日期測試:ORA-01855: AM/A.M. or PM/P.M. required
    
  3).客戶端NLS_LANG設置爲AMERICAN_AMERICA.ZHS16GBK:
      中文字符測試:插入/顯示中文字符均爲正常
      中文日期測試:ORA-01855: AM/A.M. or PM/P.M. required
  
  4).客戶端NLS_LANG設置爲AMERICAN_AMERICA.AL32UTF8:
      中文字符測試:插入/顯示中文字符均爲亂碼
      中文日期測試:ORA-01855: AM/A.M. or PM/P.M. required
    
  5).客戶端NLS_LANG設置爲SIMPLIFIED CHINESE_CHINA.ZHS16GBK:
      中文字符測試:插入/顯示中文均爲正常
      中文日期測試:插入/顯示中文日期均爲正常,格式爲DD-MM-YY(例如:08-1月 -08)  

4.測試結論:
  從測試結果來看,當數據庫端字符集爲ZHS16GBK時,可以使到中文字符被正常插入/顯示的NLS_LANG的字符集爲:ZHS16GBK。
  
  並且要使到中文格式的時間可以被正確插入,則NLS_LANG的LANGUAGE和TERRITORY設置必須爲:SIMPLIFIED CHINESE_CHINA
===================================================================

【測試總結】=================================================================== 從上面兩個測試的結果就能夠明顯看出,把數據庫端的字符集設置爲AL32UTF8比起ZHS16GBK更加有優點。UTF8支持從客戶端應用字符集爲WE8MSWIN125二、ZHS16GBK、AL32UTF8的環境下進行中文字符的插入,而ZHS16GBK只支持客戶端應用字符集爲ZHS16GBK環境下的的中文字符插入。其次咱們來看看日期格式爲:01/08/2008 04:14:00 下午的記錄爲何只能在NLS_LANG的LANGUAGE和TERRITORY爲SIMPLIFIED CHINESE_CHINA的狀況下才能正確插入?咱們知道客戶端NLS_LANG的值由3部分構成,即<LANUAGE>_<TERRITORY>.<CHARACTERSET>,而掌管日期中月份和日顯示的偏偏就是<LANGUAGE>部分,因此很明顯<LANGUAGE>爲AMERICAN的狀況下,是不可能正確插入的(西方用AM、PM來表示上、下午)。依次類推,若是之後出現貨幣和數字格式、地區和計算星期及日期的習慣插入、轉換失敗,那麼咱們就要檢查第二個元素<TERRITORY>。
相關文章
相關標籤/搜索