標籤:執行 row 用戶端 2.0 客戶 讀取 過程 漢字 dba
原文連結:http://blog.csdn.net/dbanote/article/details/9158367
一、查詢服務端字元集 select userenv(‘language‘) from dual; USERENV(‘LANGUAGE‘) ---------------------------------------------------- SIMPLIFIED CHINESE_CHINA.ZHS16GBK二、 用戶端NLS_LANG參數(即sqlplus的參數)該參數用於向Oracle指示用戶端作業系統(sqlplus用戶端)的字元集。 select * from v$nls_parameters where parameter=‘NLS_CHARACTERSET‘; PARAMETER VALUE ------------------------------ ------------------------------ NLS_CHARACTERSET ZHS16GBK 設定用戶端NLS_LANG C:\Users\85243>set nls_lang=Simplified Chinese_China.ZHS16GBK C:\Users\85243>set nls_lang=Simplified Chinese_China.AL32UTF8三、用戶端作業系統字元集 C:\Users\85243>chcp 活動字碼頁: 936 936代表的是gbk編碼 65001代表的是utf-8
有了以上3個基本概念之後,我來闡述一下Oracle字元集轉換的基本原則:
1.設定用戶端的NLS_LANG為用戶端作業系統的字元集
2.如果資料庫字元集等於NLS_LANG,資料庫和用戶端傳輸字元時不作任何轉換
3.如果它們倆不等,則需要在不同字元集間轉換,只有用戶端作業系統字元集是資料庫字元集子集的基礎上才能正確轉換,否則會出現亂碼。
幾種常見情況分析 1. 資料庫字元集為Unicode(UTF-8編碼) 我們的資料庫版本是10.2.0.4.0,資料庫字元集是: SQL> select * from v$nls_parameters where parameter=‘NLS_CHARACTERSET‘; PARAMETER VALUE ---------------------------------------- ------------------------------ NLS_CHARACTERSET AL32UTF8 2. 用戶端作業系統字元集為字碼頁936(字元集為ZHS16GBK) 可以使用chcp獲得windows的字碼頁(code page) C:\Documents and Settings\a105024\Desktop>chcp Active code page: 936 3. 建立測試表 SQL> create table test(id number,var varchar2(30)); Table created. 4. 插入資料 這裡在同一個作業系統啟動兩個session,session1的NLS_LANG設為和資料庫字元集一樣(即AL32UTF8): C:\Documents and Settings\a105024\Desktop>set nls_lang=Simplified Chinese_China.AL32UTF8 串連資料庫並插入一條資料: Session_1>insert into test values(1,‘中國‘); 1 row created. Session_1>commit; Commit complete. session2的NLS_LANG設為和用戶端作業系統一樣(即ZHS16GBK): C:\Documents and Settings\a105024\Desktop>set nls_lang=Simplified Chinese_China.ZHS16GBK 串連資料庫並插入一條資料: Session_2>insert into test values(2,‘中國‘); 1 row created. Session_2>commit; Commit complete. 5. 執行查詢 在session 1上執行查詢: Session_1>select * from test; ID VAR ---------- --------------------- 1 中國 2 涓 浗 在session 2上執行查詢: Session_2>select * from test; ID VAR ---------- -------------------- 1 ??? 2 中國 上面例子看起來很詭異,session1和2都能正常顯示自己插入的字串,又都不能正常顯示對方插入的字串。為了弄清楚,我們首先得知道資料庫裡對這兩個字串是怎麼儲存的。我們可以使用dump函數獲得字元在資料庫的編碼: SQL> select id,dump(var,1016) from test; ID DUMP(VAR,1016) -- ------------------------------------------------------------ 1 Typ=1 Len=4 CharacterSet=AL32UTF8: d6,d0,b9,fa 2 Typ=1 Len=6 CharacterSet=AL32UTF8: e4,b8,ad,e5,9b,bd 根據AL32UTF8的編碼,“中國”兩字的正確編碼為(都為3個位元組):中--e4,b8,ad國--e5,9b,bd因此session 1插入的字串在資料庫中的編碼是錯誤的,session 2正確。情境1:session 1插入,session 1查詢,在資料庫中儲存錯誤,但顯示正確。 插入過程: ”中國“兩字在用戶端作業系統字元集ZHS16GBK中的編碼是”d6,d0,b9,fa",由於NLS_LANG和資料庫字元集相同,資料庫端對用戶端傳過來的字元編碼不進行任何轉換直接存入資料庫,因此資料庫中儲存的編碼也是“d6,d0,b9,fa”, 讀取過程: 資料庫端讀取的編碼是“d6,d0,b9,fa”,由於NLS_LANG和資料庫字元集相同,用戶端對資料庫端傳過來的字元編碼不進行任何轉換直接顯示,編碼”d6,d0,b9,fa“在用戶端作業系統字元集ZHS16GBK對應的漢字為“中國”。情境2:session 1插入,session 2查詢,在資料庫中儲存錯誤,顯示也錯誤。 插入過程和情境1一樣,這裡就不再累述。 讀取過程: 資料庫端讀取的編碼是“d6,d0,b9,fa”,由於NLS_LANG和資料庫字元集不同,用戶端對資料庫端傳過來的字元編碼進行轉換,資料庫端字元集AL32UTF8裡編為“d6,d0,b9,fa”無法在用戶端作業系統字元集ZHS16GBK裡找到對應的編碼,所以只好用?代替。 情境3:session 2插入,session 1查詢,在資料庫中儲存正確,但顯示錯誤。 插入過程: ”中國“兩字在用戶端作業系統字元集ZHS16GBK中的編碼是”d6,d0,b9,fa",由於NLS_LANG和資料庫字元集不同,Oracle會進行字元編碼轉換,也就是將字元集ZHS16GBK裡“中國”的編碼“d6,d0,b9,fa"轉換為字元集"AL32UTF8"裡”中國“的編碼”e4,b8,ad,e5,9b,bd“。 讀取過程: 資料庫端讀取的編碼是”e4,b8,ad,e5,9b,bd“,由於NLS_LANG和資料庫字元集相同,用戶端對資料庫端傳過來的字元編碼不進行任何轉換直接顯示,編碼”e4,b8,ad,e5,9b,bd“在用戶端作業系統字元集ZHS16GBK對應的漢字為“涓 浗”(原本2個字元,現在變成了3個字元,因為ZHS16GBK的漢字以2個位元組編碼)。情境4:session 2插入,session 2查詢,在資料庫中儲存正確,顯示也正確。 插入過程和情境3類似。 讀取過程: 資料庫端讀取的編碼是”e4,b8,ad,e5,9b,bd“,由於NLS_LANG和資料庫字元集不同,用戶端對資料庫端傳過來的字元編碼進行轉換,資料庫端字元集AL32UTF8裡”中國“兩字的編碼”e4,b8,ad,e5,9b,bd“轉換成用戶端作業系統字元集ZHS16GBK裡“中國”兩字的編碼“d6,d0,b9,fa",並正常顯示。
原文:
http://blog.csdn.net/dbanote/article/details/9158367
oracle字元編碼的理解