nls_sort與漢字排序
朋友在進行報表需求評估的時候,突然問筆者一個問題:在資料庫裡面,漢字進行排序的順序是按照什麼方法?對空值null,是排在第一位還是最後一位?當時做了一個簡單的小實驗,立刻獲得了答案。但是之後,在想是不是還有其它方式進行排序的支援呢?這時可以使用nls_sort引數設定。
nls_sort是Oracle的初始化引數之一。根據官方文件的介紹,該引數“specifies the collating sequence for Order by queries”,也就是說,設定該引數是可以控制SQL order by語句顯示結果順序的依據的。
初始化環境
首先,構建實驗環境和資料。
//10gR2資料庫環境
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod
PL/SQL Release 10.2.0.1.0 - Production
CORE 10.2.0.1.0 Production
TNS for 32-bit Windows: Version 10.2.0.1.0 - Production
NLSRTL Version 10.2.0.1.0 – Production
//資料表T,其中包括數字和字元型別欄位
SQL> desc t;
Name Type Nullable Default Comments
------ ------------ -------- ------- --------
IDNUM NUMBER(10) Y
ENCHAR VARCHAR2(10) Y
CHCHAR VARCHAR2(10) Y
//包括中文、英文和空行;
SQL> select * from t;
IDNUM ENCHAR CHCHAR
----------- ---------- ----------
1 adf 中國
2 flsd
3 sd 阿姨
4 lk 實驗
5 罪惡
6 mll 饕餮
21 lf lfs
7 rows selected
nls_sort相關引數情況,發現nls_sort引數的設定是空。
SQL> show parameter nls
NAME TYPE VALUE
------------------------------------ ----------- --------
nls_calendar string
nls_comp string
(篇幅原因,省略…)
nls_language string SIMPLIFIED CHINESE
nls_sort string
nls_sort取值分為兩種型別:binary或者linguistic_definition。binary表示排序標準按照字元儲存的順序進行儲存,這種方式對DBMS進行處理來說是最快的一種排序方式。linguistic_definition是指語系定義,通常一種語言language要對應特定的一系列語系定義。
當前系統中,我們發現nls_sort引數並沒有進行定義。在沒有定義nls_sort的時候,系統採用的排序方式與nls_language所對應的預設排序Default Sort方式相同。
在Oracle文件庫的《Globalization Support Guide》中,定義了各種language對應的Default Sort方式。當前nls_language取值為“SIMPLIFIED CHINESE”,對應的預設排序方式就是binary。
預設排序方式
在當前系統中,採用binary作為排序方式,對應的是儲存的二進位制編碼順序。下面透過實驗來證明。
SQL> col idnum for a5;
SQL> select t.*, dump(chchar,1016) from t order by chchar;
IDNUM ENCHAR CHCHAR DUMP(CHCHAR,1016)
----- ---------- ---------- --------------------------------------------------------------------------------
21 lf lfs Typ=1 Len=3 CharacterSet=ZHS16GBK: 6c,66,73
3 sd 阿姨 Typ=1 Len=4 CharacterSet=ZHS16GBK: b0,a2,d2,cc
4 lk 實驗 Typ=1 Len=4 CharacterSet=ZHS16GBK: ca,b5,d1,e9
1 adf 中國 Typ=1 Len=4 CharacterSet=ZHS16GBK: d6,d0,b9,fa
5 罪惡 Typ=1 Len=4 CharacterSet=ZHS16GBK: d7,ef,b6,f1
6 mll 饕餮 Typ=1 Len=4 CharacterSet=ZHS16GBK: f7,d2,f7,d1
2 flsd NULL
7 rows selected
透過dump成16進位制的字元編碼,可以看出binary排序方式。而且,在binary方式下,空會被放在最末尾位置。
中文可用排序方式
從Oracle9i開始,對中文語言方式(Simplified Chinese和Traditional Chinese)提供了多種排序方式。
排序方式名稱 |
描述 |
SCHINESE_RADICAL_M |
針對簡體中文,按照部首(第一順序)、筆劃(第二順序)排序 |
SCHINESE_STROKE_M |
針對簡體中文,按照筆劃(第一順序)、部首(第二順序)排序 |
SCHINESE_PINYIN_M |
針對簡體中文,按照拼音排序 |
TCHINESE_RADICAL_M |
針對繁體中文,按照部首(第一順序)、筆劃(第二順序)排序 |
TCHINESE_STROKE_M |
針對繁體中文,按照筆劃(第一順序)、部首(第二順序)排序 |
由此,就為中文進行排序提供了多種的依據和設定。
設定排序方法1——引數檔案設定
這種方法是最根本的方法。在引數檔案pfile中,設定引數nls_sort的取值。之後重新啟動資料庫例項即可。這種方法會應用排序方式到例項所有的查詢中,實際中較少使用。
設定排序方法2——Session會話級別設定
可以在會話中,透過alter session設定nls_sort取值。之後該會話就會自動應用上新的nls_sort方式。
SQL> alter session set nls_sort='SCHINESE_RADICAL_M';
Session altered
SQL> select t.*, dump(chchar,1016) from t order by chchar;
IDNUM ENCHAR CHCHAR DUMP(CHCHAR,1016)
----- ---------- ---------- --------------------------------------------------------------------------------
21 lf lfs Typ=1 Len=3 CharacterSet=ZHS16GBK: 6c,66,73
1 adf 中國 Typ=1 Len=4 CharacterSet=ZHS16GBK: d6,d0,b9,fa
4 lk 實驗 Typ=1 Len=4 CharacterSet=ZHS16GBK: ca,b5,d1,e9
5 罪惡 Typ=1 Len=4 CharacterSet=ZHS16GBK: d7,ef,b6,f1
3 sd 阿姨 Typ=1 Len=4 CharacterSet=ZHS16GBK: b0,a2,d2,cc
6 mll 饕餮 Typ=1 Len=4 CharacterSet=ZHS16GBK: f7,d2,f7,d1
2 flsd NULL
7 rows selected
SQL> alter session set nls_sort='SCHINESE_STROKE_M';
Session altered
SQL> select t.*, dump(chchar,1016) from t order by chchar;
IDNUM ENCHAR CHCHAR DUMP(CHCHAR,1016)
----- ---------- ---------- --------------------------------------------------------------------------------
21 lf lfs Typ=1 Len=3 CharacterSet=ZHS16GBK: 6c,66,73
1 adf 中國 Typ=1 Len=4 CharacterSet=ZHS16GBK: d6,d0,b9,fa
3 sd 阿姨 Typ=1 Len=4 CharacterSet=ZHS16GBK: b0,a2,d2,cc
4 lk 實驗 Typ=1 Len=4 CharacterSet=ZHS16GBK: ca,b5,d1,e9
5 罪惡 Typ=1 Len=4 CharacterSet=ZHS16GBK: d7,ef,b6,f1
6 mll 饕餮 Typ=1 Len=4 CharacterSet=ZHS16GBK: f7,d2,f7,d1
2 flsd NULL
7 rows selected
透過session級別的設定。我們可以清晰看出不同排序方法的效果。
設定排序方法3——在order by子句中直接指定
除了上述的兩種方法,還可以在select語句的order by子句中直接指定排序方式。這樣可以在SQL語句級別設定排序方式,應該是一種最靈活的控制方式。
SQL> select * from t order by chchar;
IDNUM ENCHAR CHCHAR
----------- ---------- ----------
21 lf lfs
3 sd 阿姨
4 lk 實驗
1 adf 中國
5 罪惡
6 mll 饕餮
2 flsd
7 rows selected
SQL> select * from t order by nlssort(chchar,'nls_sort=SCHINESE_RADICAL_M');
IDNUM ENCHAR CHCHAR
----------- ---------- ----------
21 lf lfs
1 adf 中國
4 lk 實驗
5 罪惡
3 sd 阿姨
6 mll 饕餮
2 flsd
7 rows selected
SQL> select * from t order by nlssort(chchar,'nls_sort=SCHINESE_STROKE_M');
IDNUM ENCHAR CHCHAR
----------- ---------- ----------
21 lf lfs
1 adf 中國
3 sd 阿姨
4 lk 實驗
5 罪惡
6 mll 饕餮
2 flsd
7 rows selected
此外,對很多的資料訪問介面,如JDBC、Hibernate和JPA,都在一定程度上支援多種排序方式的指定。具體的方式可以參見相關文獻資料,本文就不加以累述了。
最後,作為本文的結束,也作為一個新問題的起點。使用nls_sort之後,雖然可以方便的指定排序方式,但是還會帶來一些問題。其中最大的問題就是索引的失效性。nls_sort的改寫改變了原有的索引結構和順序,會導致原有的索引不能使用。從而影響整體系統效能。
在這種情況下,就需要設定一種較為特殊的索引index型別,語系linguistic Indexes,同時也要對nls_comp引數加以控制設定,這樣可以保證索引的正確設定和提高系統訪問效率。這個問題,留待我們以後繼續進行討論。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/17203031/viewspace-690198/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- js 漢字陣列按拼音排序JS陣列排序
- JavaScript按照漢字拼音順序排序JavaScript排序
- Excel表格如何按漢字的筆畫排序?Excel表格按漢字的筆畫排序的方法Excel排序
- 蒙納字型檔:深耕漢字美學與技術,讓漢字走向世界
- 漢字轉漢語拼音
- C#漢字轉漢語拼音C#
- 只提取漢字部分
- C:漢字儲存
- java 漢字轉配音Java
- PHP 將數字轉換為漢字PHP
- 阿拉伯-漢字-數字轉換
- JS 漢字轉換拼音JS
- 漢字編碼問題
- utils公共方法:將數字轉為漢字
- 正規表示式匹配漢字
- html 空白漢字佔位符HTML
- 漢字之美,拼音之韻
- notepad++搜尋所有漢字
- python中怎麼列印漢字Python
- JavaScript 漢字方式輸出星期JavaScript
- C#漢字拼音檢索C#
- utf-8的中文漢字
- C#中漢字轉拼音C#
- 多關鍵字排序排序
- 第二章 :查詢與排序-------遞迴經典問題——漢諾塔問題排序遞迴
- xpinyin:漢字轉換為拼音庫
- 04hanzi.py(漢字搜尋)
- 獲取字串中的所有漢字字串
- Oracle中文漢字佔用位元組Oracle
- Python 漢字轉拼音的庫--- PyPinyinPython
- mysql 中如何取得漢字欄位的各漢字首字母MySql
- 氣泡排序與選擇排序排序
- 86、98五筆成字字根漢字
- codeblocks執行時漢字變亂碼BloC
- 漢字描紅在Flutter側的落地Flutter
- 判斷欄位中是否有漢字
- cmd顯示漢字需要的設定
- 氣泡排序、歸併排序與快速排序比較排序
- 看懂堆排序——堆與堆排序(三)排序