Chinaunix首页 | 论坛 | 博客
  • 博客访问: 440227
  • 博文数量: 94
  • 博客积分: 3066
  • 博客等级: 中校
  • 技术积分: 908
  • 用 户 组: 普通用户
  • 注册时间: 2006-01-25 17:10
文章分类

全部博文(94)

文章存档

2016年(3)

2015年(4)

2014年(1)

2013年(9)

2012年(8)

2011年(1)

2010年(8)

2009年(4)

2008年(2)

2007年(6)

2006年(48)

我的朋友

分类: 数据库开发技术

2006-11-20 17:47:23

用排序规则特点计算汉字笔划和取得拼音首字母

  SQL SERVER的排序规则平时使用不是很多,也许不少初学者还比较陌生,但有一个错误大家应是经常碰到:  SQL  SERVER数据库,在跨库多表连接查询时,若两数据  库默认字符集不同,系统就会返回这样的错误: “无法解决  equal  to  操作的排序规则冲突。” 

一.错误分析: 

  这个错误是因为排序规则不一致造成的,我们做个测试,比如: 

create  table  #t1( 

name  varchar(20)  collate  Albanian_CI_AI_WS,     

value  int) 

create  table  #t2( 

name  varchar(20)  collate  Chinese_PRC_CI_AI_WS,         

value  int  ) 

表建好后,执行连接查询: 

select  *  from  #t1  A  inner  join  #t2  B  on  A.name=B.name   

这样,错误就出现了: 

                      服务器:  消息  446,级别  16,状态  9,行  1 

                      无法解决  equal  to  操作的排序规则冲突。 

  要排除这个错误,最简单方法是,表连接时指定它的排序规则,这样错误就 

不再出现了。语句这样写: 

select  *   

from  #t1  A  inner  join  #t2  B   

on  A.name=B.name  collate  Chinese_PRC_CI_AI_WS 

二.排序规则简介: 

        什么叫排序规则呢?MS是这样描述的:"在  Microsoft  SQL  Server  2000  中, 

字符串的物理存储由排序规则控制。排序规则指定表示每个字符的位模式以及存 

储和比较字符所使用的规则。" 

  在查询分析器内执行下面语句,可以得到SQL SERVER支持的所有排序规则。 

    select  *  from  ::fn_helpcollations()   

排序规则名称由两部份构成,前半部份是指本排序规则所支持的字符集。 

如: 

  Chinese_PRC_CS_AI_WS   

前半部份:指UNICODE字符集,Chinese_PRC_指针对大陆简体字UNICODE的排序规则。 

排序规则的后半部份即后缀  含义:   

  _BIN  二进制排序   

  _CI(CS)  是否区分大小写,CI不区分,CS区分 

  _AI(AS)  是否区分重音,AI不区分,AS区分    

  _KI(KS)  是否区分假名类型,KI不区分,KS区分  

        _WI(WS)  是否区分宽度  WI不区分,WS区分  

区分大小写:如果想让比较将大写字母和小写字母视为不等,请选择该选项。 

区分重音:如果想让比较将重音和非重音字母视为不等,请选择该选项。如果选择该选项, 

                  比较还将重音不同的字母视为不等。 

区分假名:如果想让比较将片假名和平假名日语音节视为不等,请选择该选项。 

区分宽度:如果想让比较将半角字符和全角字符视为不等,请选择该选项 

   

三.排序规则的应用: 

  SQL  SERVER提供了大量的WINDOWS和SQLSERVER专用的排序规则,但它的应用往往 

被开发人员所忽略。其实它在实践中大有用处。 

  例1:让表NAME列的内容按拼音排序: 

create  table  #t(id  int,name  varchar(20)) 

insert  #t  select  1,'中' 

union  all  select  2,'国' 

union  all  select  3,'人' 

union  all  select  4,'阿' 

select  *  from  #t  order  by  name  collate  Chinese_PRC_CS_AS_KS_WS   

drop  table  #t 

/*结果: 

id                    name                                   

-----------  --------------------   

4                      阿 

2                      国 

3                      人 

1                      中 

*/ 

  例2:让表NAME列的内容按姓氏笔划排序: 

create  table  #t(id  int,name  varchar(20)) 

insert  #t  select  1,'三' 

union  all  select  2,'乙' 

union  all  select  3,'二' 

union  all  select  4,'一' 

union  all  select  5,'十' 

select  *  from  #t  order  by  name  collate  Chinese_PRC_Stroke_CS_AS_KS_WS     

drop  table  #t 

/*结果: 

id                    name                                   

-----------  --------------------   

4                      一 

2                      乙 

3                      二 

5                      十 

1                      三 

*/ 

四.在实践中排序规则应用的扩展 

  SQL  SERVER汉字排序规则可以按拼音、笔划等排序,那么我们如何利用这种功能 

来处理汉字的一些难题呢?我现在举个例子: 

          用排序规则的特性计算汉字笔划 

  要计算汉字笔划,我们得先做准备工作,我们知道,WINDOWS多国汉字,UNICODE目前 

收录汉字共20902个。简体GBK码汉字UNICODE值从19968开始。 

  首先,我们先用SQLSERVER方法得到所有汉字,不用字典,我们简单利用SQL语句就 

可以得到: 

select  top  20902  code=identity(int,19968,1)  into  #t  from  syscolumns  a,syscolumns  b 

再用以下语句,我们就得到所有汉字,它是按UNICODE值排序的: 

  select  code,nchar(code)  as  CNWord  from  #t   

  然后,我们用SELECT语句,让它按笔划排序。 

select  code,nchar(code)  as  CNWord   

from  #t   

order  by  nchar(code)  collate  Chinese_PRC_Stroke_CS_AS_KS_WS,code 

结果: 

code                CNWord   

-----------  ------   

19968              一 

20008              丨 

20022              丶 

20031              丿 

20032              乀 

20033              乁 

20057              乙 

20058              乚 

20059              乛 

20101              亅 

19969              丁 

.......... 

     从上面的结果,我们可以清楚的看到,一笔的汉字,code是从19968到20101,从小到大排,但到 

了二笔汉字的第一个字“丁”,CODE为19969,就不按顺序而重新开始了。有了这结果,我们就可以轻 

松的用SQL语句得到每种笔划汉字归类的第一个或最后一个汉字。 

下面用语句得到最后一个汉字: 

create  table  #t1(id  int  identity,code  int,cnword  nvarchar(2)) 

insert  #t1(code,cnword) 

select  code,nchar(code)  as  CNWord    from  #t   

order  by  nchar(code)  collate  Chinese_PRC_Stroke_CS_AS_KS_WS,code 

select  A.cnword   

from  #t1  A   

left  join  #t1  B  on  A.id=B.id-1  and  A.code

where  B.code  is  null 

order  by  A.id 

得到36个汉字,每个汉字都是每种笔划数按Chinese_PRC_Stroke_CS_AS_KS_WS排序规则排序后的 

最后一个汉字: 

亅阝马风龙齐龟齿鸩龀龛龂龆龈龊龍龠龎龐龑龡龢龝齹龣龥齈龞麷鸞麣龖龗齾齉龘 

  上面可以看出:“亅”是所有一笔汉字排序后的最后一个字,“阝”是所有二笔汉字排序后的最后 

一个字......等等。 

  但同时也发现,从第33个汉字“龗(33笔)”后面的笔划有些乱,不正确。但没关系,比“龗”笔划 

多的只有四个汉字,我们手工加上:齾35笔,齉36笔,靐39笔,龘64笔 

建汉字笔划表(TAB_HZBH): 

create  table  tab_hzbh(id  int  identity,cnword  nchar(1)) 

--先插入前33个汉字 

insert  tab_hzbh 

select  top  33  A.cnword   

from  #t1  A   

left  join  #t1  B  on  A.id=B.id-1  and 

阅读(1742) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~