oracle 使用order by 对汉字进行多字段排序

今天遇到一个奇怪的问题, 在两个不同的数据库里执行同样的sql语句, 相同的数据却排序结果不一致。

 
执行sql如下:

select decode(brch.LOCAL, 'Y', '国内', '国际') as local,
brch.COUNTRY,
brch.PROVINCE,
brch.CITY,
brch.AREA,
brch.VENDOR,
brch.SERVICE_PROVIDER,
brch.SERVICE_SITE_ADDR
from lpmsrepdata.vip_sx_service_site_brch brch
where brch.type_cd = 'TJJG'
and brch.active_flg = 'Y'
AND brch.PROVINCE = trim('湖北')
order by brch.local,
brch.country,
brch.province,
brch.city,
brch.area,
brch.service_provider,
brch.service_site_addr asc

执行结果分别为;

1.

LOCAL COUNTRY                                                               PROVINCE                                                              CITY                                                                         AREA                                                                       VENDOR                                                                 SERVICE_PROVIDER                                              SERVICE_SITE_ADDR
------ -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- --------------------------------------------------------------------------------
国内 中国                                                                          湖北                                                                          武汉市                                                                      汉阳区                                                                                                                                                       美年大健康-武汉美年(原一博体检中心)            武汉市汉阳区二桥路19号汉江阳光城1-2层(原一博体检中心)
国内 中国                                                                          湖北                                                                          武汉市                                                                      江岸区                                                                                                                                                       美年大健康-武汉美年                                              武汉市江岸区黄孝河路107号花桥大厦1-3楼(原梦天湖大酒店)
国内 中国                                                                          湖北                                                                          武汉市                                                                      武昌区                                                                                                                                                       美年大健康-武汉美年                                              武汉市武昌区中北路108号广泽中心4F
 

2.


LOCAL COUNTRY                                                               PROVINCE                                                              CITY                                                                         AREA                                                                       VENDOR                                                                 SERVICE_PROVIDER                                              SERVICE_SITE_ADDR
------ -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- --------------------------------------------------------------------------------
国内 中国                                                                          湖北                                                                          武汉市                                                                      武昌区                                                                                                                                                       美年大健康-武汉美年                                              武汉市武昌区中北路108号广泽中心4F
国内 中国                                                                          湖北                                                                          武汉市                                                                      汉阳区                                                                                                                                                       美年大健康-武汉美年(原一博体检中心)            武汉市汉阳区二桥路19号汉江阳光城1-2层(原一博体检中心)
国内 中国                                                                          湖北                                                                          武汉市                                                                      江岸区                                                                                                                                                       美年大健康-武汉美年                                              武汉市江岸区黄孝河路107号花桥大厦1-3楼(原梦天湖大酒店)
 

查了下, oracle对于order  by的排序规则

Oracle provides the following types of sorts:
Binary sort
Monolingual linguistic sort
Multilingual linguistic sort
注:后两种可统一为linguistic(语言的) sort

 

而在汉语里,

Chinese is how to sort?

Prior to Oracle9i, the Chinese are in accordance with the sort of binary encoding.
Added in oracle9i in accordance with pinyin, radical, stroke order functions. Set NLS_SORT value
SCHINESE_RADICAL_M in accordance with the radical (first order), stroke (second order) Sort
SCHINESE_STROKE_M in accordance with the stroke (first order), radicals (second order) Sort
SCHINESE_PINYIN_M sorted according to Pinyin

所以在排序时需要考虑;排序综合考虑数据库字符集、NLS_SORT

 

 

查看数据库的字符集;

SQL> select * from v$nls_parameters  where  PARAMETER like '%NLS_CHARACTERSET%';
 
PARAMETER                                          VALUE
---------------------------------------------------------------- ----------------------------------------------------------------
NLS_CHARACTERSET                           AL32UTF8

 

SQL> select * from v$nls_parameters  where  PARAMETER like '%NLS_CHARACTERSET%';
 
PARAMETER                                          VALUE
---------------------------------------------------------------- ----------------------------------------------------------------
NLS_CHARACTERSET                           ZHS16GBK
 
SQL>

 

如果字符集为ZHS16GBK/ZH16GBK,那么使用order by默认是按照汉字的拼音顺序进行排序的;如果为其他(如UTF8),那么汉字的排序是按照BINARY排序的。

数据库字符集不为中文字符集的情况下怎样让其按照汉字拼音排序?答案是设置NLS_SORT

果然不一样,但是nls_sort确实一样的。

SQL> select value from nls_database_parameters where parameter='NLS_SORT'; 
 
VALUE
--------------------------------------------------------------------------------
BINARY

 

SQL> select value from nls_database_parameters where parameter='NLS_SORT'; 
 
VALUE
--------------------------------------------------------------------------------
BINARY


字符集为中文字符集、NLS_SORT为BINARY时,汉字是按汉字拼音排序;
字符集为非中文字符集(如UTF8)、NLS_SORT为BINARY时,汉字按二进制编码(BINARY)排序。
所以,对非中文字符集库: 可通过设置其NLS_SORT来实现汉字的定制化排序;改变当前会话的NLS_SORT:

ALTER session SET NLS_SORT = SCHINESE_PINYIN_M  ;

再看下结果,就都一致了..

LOCAL COUNTRY                                           PROVINCE                                          CITY                                                     AREA                                                   VENDOR                                             SERVICE_PROVIDER                          SERVICE_SITE_ADDR
----- ------------------------------------------------------------ ------------------------------------------------------------ ------------------------------------------------------------ ------------------------------------------------------------ ------------------------------------------------------------ ------------------------------------------------------------ --------------------------------------------------------------------------------
国内 中国                                                      湖北                                                      武汉市                                                  汉阳区                                                                                                               美年大健康-武汉美年(原一博体检中心) 武汉市汉阳区二桥路19号汉江阳光城1-2层(原一博体检中心)
国内 中国                                                      湖北                                                      武汉市                                                  江岸区                                                                                                               美年大健康-武汉美年                          武汉市江岸区黄孝河路107号花桥大厦1-3楼(原梦天湖大酒店)
国内 中国                                                      湖北                                                      武汉市                                                  武昌区                                                                                                               美年大健康-武汉美年                          武汉市武昌区中北路108号广泽中心4F
 

 

LOCAL COUNTRY                                           PROVINCE                                          CITY                                                     AREA                                                   VENDOR                                             SERVICE_PROVIDER                          SERVICE_SITE_ADDR
----- ------------------------------------------------------------ ------------------------------------------------------------ ------------------------------------------------------------ ------------------------------------------------------------ ------------------------------------------------------------ ------------------------------------------------------------ --------------------------------------------------------------------------------
国内 中国                                                      湖北                                                      武汉市                                                  汉阳区                                                                                                               美年大健康-武汉美年(原一博体检中心) 武汉市汉阳区二桥路19号汉江阳光城1-2层(原一博体检中心)
国内 中国                                                      湖北                                                      武汉市                                                  江岸区                                                                                                               美年大健康-武汉美年                          武汉市江岸区黄孝河路107号花桥大厦1-3楼(原梦天湖大酒店)
国内 中国                                                      湖北                                                      武汉市                                                  武昌区                                                                                                               美年大健康-武汉美年                          武汉市武昌区中北路108号广泽中心4F
 


看下如下:

Prior to Oracle9i, the Chinese is based on binary coding to sort. The oracle9i added in accordance with the phonetic, radical, stroke sorting.
1, set parameter values NLS_SORT
SCHINESE_RADICAL_M accordance with the radical (first order), stroke (second order) to sort
SCHINESE_STROKE_M accordance with the stroke (first order), radical (second order) to sort
SCHINESE_PINYIN_M sorted according to Pinyin
2, Session-level settings, modify the default ORACLE field Sort by:
According to Pinyin: alter session set nls_sort = SCHINESE_PINYIN_M;
According to stroke: alter session set nls_sort = SCHINESE_STROKE_M;
According to the radical: alter session set nls_sort = NLS_SORT = SCHINESE_RADICAL_M;
3, the statement level is set Sort by:
Oracle according to alphabetical order
Select * From [tablename] order By nlssort (colname, 'NLS_SORT = SCHINESE_STROKE_M');
Oracle accordance with the radical sort
Select * From [tablename] order By nlssort (colname, 'NLS_SORT = SCHINESE_RADICAL_M');
Oracle sorted according to Pinyin
Select * From [tablename] order By nlssort (colname, 'NLS_SORT = SCHINESE_PINYIN_M');
4, modify the system parameters (database where the operating system):
set NLS_SORT = SCHINESE_RADICAL_M; export NLS_SORT (sh)
setenv NLS_SORT SCHINESE_RADICAL_M (csh)
HKLC \ SOFTWARE \ ORACLE \ home0 \ NLS_SORT (win registry)

 

引用其他人的实验:

如果数据库字符集选用的是ZH16GBK,那么使用order by默认是按照汉字的拼音顺序进行排序的。有方法改变这个默认规则么?
答案是肯定的,Oracle针对简体中文提供三种排序方法,主要是围绕“拼音”、“部首”和“笔画数”展开的。
通过实验,给大家展示一下NLSSORT在改变简体汉字排序规则方面的魅力。

1.在Oracle的官方文档中关于排序有如下描述
“Linguistic Sorts”
http://download.oracle.com/docs/cd/B19306_01/server.102/b14225/applocaledata.htm#sthref2000
其中表“Table A-15 Multilingual LInguistic Sorts”中我们关注一下有关中文排序的内容(前三条与简体中文排序有关,后两条与繁体中文排序有关):
1)SCHINESE_RADICAL_M
Simplified Chinese sort based on radical as primary order and number of strokes order as secondary order
注释:简体中文按照第一顺序是“部首”第二顺序是“笔画数”进行排序;

2)SCHINESE_STROKE_M
Simplified Chinese sort uses number of strokes as primary order and radical as secondary order
注释:简体中文按照第一顺序“笔画数”是第二顺序是“部首”进行排序;

3)SCHINESE_PINYIN_M
Simplified Chinese PinYin sorting order
注释:简体中文按照“拼音”进行排序;

4)TCHINESE_RADICAL_M
Traditional Chinese sort based on radical as primary order and number of strokes order as secondary order
注释:繁体中文按照第一顺序是“部首”第二顺序是“笔画数”进行排序;

5)TCHINESE_STROKE_M
Traditional Chinese sort uses number of strokes as primary order and radical as secondary order. It supports supplementary characters.
注释:繁体中文按照第一顺序“笔画数”是第二顺序是“部首”进行排序;

2.创建实验表T,并初始化六条记录
sec@secooler> create table t (x varchar2(10));
sec@secooler> insert into t values ('侯');
sec@secooler> insert into t values ('你');
sec@secooler> insert into t values ('做');
sec@secooler> insert into t values ('拉');
sec@secooler> insert into t values ('推');
sec@secooler> insert into t values ('拆');
sec@secooler> commit;
sec@secooler> select * from t;

X
------------------------------







6 rows selected.

3.确认数据库版本和数据库字符集
sec@secooler> select * from v$version;

BANNER
----------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - 64bit Production
PL/SQL Release 11.2.0.1.0 - Production
CORE    11.2.0.1.0      Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production

sec@secooler> select userenv('language') from dual;

USERENV('LANGUAGE')
-----------------------------------------------------------
AMERICAN_AMERICA.ZHS16GBK

4.在此环境下,查看默认的汉字排序规则
sec@secooler> select * from t order by x;

X
------------------------------







6 rows selected.

可见,此时的默认汉字排序规则是“拼音”。

5.使用nlssort强制按照拼音排序的方法
sec@secooler> select * from t order by nlssort(x,'NLS_SORT=SCHINESE_PINYIN_M');

X
------------------------------







6 rows selected.

6.使用nlssort强制按照“部首”(第一顺序)和“笔画数”(第二顺序)排序的方法
sec@secooler> select * from t order by nlssort(x,'NLS_SORT=SCHINESE_RADICAL_M');

X
------------------------------







6 rows selected.

单人旁的汉字在前,提手旁汉字在后;单人旁的三个汉字进一步又是按照笔画数多少进行的排序。

7.使用nlssort强制按照“笔画数”(第一顺序)和“部首”(第二顺序)排序的方法
sec@secooler> select * from t order by nlssort(x,'NLS_SORT=SCHINESE_STROKE_M');

X
------------------------------







6 rows selected.

可见,越往后的汉字的笔画数越多。

8.Oracle官方文档中关于NSLSORT函数的描述参考
http://download.oracle.com/docs/cd/E11882_01/server.112/e10592/functions111.htm#SQLRF00678

9.小结
NSLSORT函数在国际化支持上提供了一个非常好的排序解决方案。在具体应用环境下有其重要的意义。善用之。

 

 

 

 

 

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

kuifeng.dong

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值