我们在createtable时经常会碰到这样的语句,例如:passwordnvarchar(10)collatechinese_prc_ci_asnull,那它到底是什么意思呢?不妨看看下面:
首先,collate是一个子句,可应用于数据库定义或列定义以定义排序规则,或应用于字符串表达式以应用排序规则投影。
语法是collatecollation_name
collation_name::={windows_collation_name}|{sql_collation_name}
参数collate_name是应用于表达式、列定义或数据库定义的排序规则的名称。collation_name可以只是指定的Windows_collation_name或SQL_collation_name。
Windows_collation_name是Windows排序规则的排序规则名称。参见Windows排序规则名称。SQL_collation_name是SQL排序规则的排序规则名称。参见SQL排序规则名称。
下面简单介绍一下排序规则:
什么叫排序规则呢?MS是这样描述的:"在MicrosoftSQLServer2000中,字符串的物理存储由排序规则控制。排序规则指定表示每个字符的位模式以及存储和比较字符所使用的规则。"在查询分析器内执行下面语句,可以得到SQLSERVER支持的所有排序规则。
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区分
区分大小写:如果想让比较将大写字母和小写字母视为不等,请选择该选项。区分重音:如果想让比较将重音和非重音字母视为不等,请选择该选项。如果选择该选项,比较还将重音不同的字母视为不等。区分假名:如果想让比较将片假名和平假名日语音节视为不等,请选择该选项。区分宽度:如果想让比较将半角字符和全角字符视为不等,请选择该选项
利用排序规则特点计算汉字笔划和取得拼音首字母
一.错误分析:这个错误是因为排序规则不一致造成的,我们做个测试,比如:createtable#t1(namevarchar(20)collateAlbanian_CI_AI_WS,valueint)
createtable#t2(namevarchar(20)collateChinese_PRC_CI_AI_WS,valueint)
表建好后,执行连接查询:
select*from#t1Ainnerjoin#t2BonA.name=B.name
这样,错误就出现了:
服务器:消息446,级别16,状态9,行1无法解决equalto操作的排序规则冲突。要排除这个错误,最简单方法是,表连接时指定它的排序规则,这样错误就不再出现了。语句这样写:
select*from#t1Ainnerjoin#t2BonA.name=B.namecollateChinese_PRC_CI_AI_WS
二.排序规则简介:
三.排序规则的应用:SQLSERVER提供了大量的WINDOWS和SQLSERVER专用的排序规则,但它的应用往往被开发人员所忽略。其实它在实践中大有用处。
例1:让表NAME列的内容按拼音排序:
createtable#t(idint,namevarchar(20))insert#tselect1,'中'unionallselect2,'国'unionallselect3,'人'unionallselect4,'阿'
select*from#torderbynamecollateChinese_PRC_CS_AS_KS_WSdroptable#t/*结果:idname-------------------------------4阿2国3人1中*/
例2:让表NAME列的内容按姓氏笔划排序:
createtable#t(idint,namevarchar(20))
insert#tselect1,'三'unionallselect2,'乙'unionallselect3,'二'unionallselect4,'一'unionallselect5,'十'select*from#torderbynamecollateChinese_PRC_Stroke_CS_AS_KS_WSdroptable#t/*结果:idname-------------------------------4一2乙3二5十1三*/
四.在实践中排序规则应用的扩展SQLSERVER汉字排序规则可以按拼音、笔划等排序,那么我们如何利用这种功能来处理汉字的一些难题呢?我现在举个例子:
用排序规则的特性计算汉字笔划
要计算汉字笔划,我们得先做准备工作,我们知道,WINDOWS多国汉字,UNICODE目前收录汉字共20902个。简体GBK码汉字UNICODE值从19968开始。首先,我们先用SQLSERVER方法得到所有汉字,不用字典,我们简单利用SQL语句就可以得到:
selecttop20902code=identity(int,19968,1)into#tfromsyscolumnsa,syscolumnsb
再用以下语句,我们就得到所有汉字,它是按UNICODE值排序的:
selectcode,nchar(code)asCNWordfrom#t
然后,我们用SELECT语句,让它按笔划排序。
selectcode,nchar(code)asCNWordfrom#torderbynchar(code)collateChinese_PRC_Stroke_CS_AS_KS_WS,code
结果:codeCNWord-----------------19968一20008丨20022丶20031丿20032乀20033乁20057乙20058乚20059乛20101亅19969丁..........
createtable#t1(idintidentity,codeint,cnwordnvarchar(2))
insert#t1(code,cnword)selectcode,nchar(code)asCNWordfrom#torderbynchar(code)collateChinese_PRC_Stroke_CS_AS_KS_WS,code
selectA.cnwordfrom#t1Aleftjoin#t1BonA.id=B.id-1andA.codewhereB.codeisnullorderbyA.id
得到36个汉字,每个汉字都是每种笔划数按Chinese_PRC_Stroke_CS_AS_KS_WS排序规则排序后的最后一个汉字:
亅阝马风龙齐龟齿鸩龀龛龂龆龈龊龍龠龎龐龑龡龢龝齹龣龥齈龞麷鸞麣龖龗齾齉龘
建汉字笔划表(TAB_HZBH):createtabletab_hzbh(idintidentity,cnwordnchar(1))--先插入前33个汉字inserttab_hzbhselecttop33A.cnwordfrom#t1Aleftjoin#t1BonA.id=B.id-1andA.codewhereB.codeisnullorderbyA.id--再加最后四个汉字setidentity_inserttab_hzbhongoinserttab_hzbh(id,cnword)select35,N'齾'unionallselect36,N'齉'unionallselect39,N'靐'unionallselect64,N'龘'gosetidentity_inserttab_hzbhoffgo
declare@anchar(1)set@a='国'selecttop1idfromtab_hzbhwherecnword>=@acollateChinese_PRC_Stroke_CS_AS_KS_WSorderbyid
上面所有准备过程,只是为了写下面这个函数,这个函数撇开上面建的所有临时表和固定表,为了通用和代码转移方便,把表tab_hzbh的内容写在语句内,然后计算用户输入一串汉字的总笔划:
--函数调用实例:selectdbo.fun_getbh('中华人民共和国'),dbo.fun_getbh('中華人民共和國')执行结果:笔划总数分别为39和46,简繁体都行。
用排序规则的特性得到汉字拼音首字母
用得到笔划总数相同的方法,我们也可以写出求汉字拼音首字母的函数。如下:
createfunctionfun_getPY(@strnvarchar(4000))returnsnvarchar(4000)asbegindeclare@wordnchar(1),@PYnvarchar(4000)set@PY=''whilelen(@str)>0beginset@word=left(@str,1)--如果非汉字字符,返回原字符set@PY=@PY+(casewhenunicode(@word)between19968and19968+20901then(selecttop1PYfrom(select'A'asPY,N'驁'aswordunionallselect'B',N'簿'unionallselect'C',N'錯'unionallselect'D',N'鵽'unionallselect'E',N'樲'unionallselect'F',N'鰒'unionallselect'G',N'腂'unionallselect'H',N'夻'unionallselect'J',N'攈'unionallselect'K',N'穒'unionallselect'L',N'鱳'unionallselect'M',N'旀'unionallselect'N',N'桛'unionallselect'O',N'漚'unionallselect'P',N'曝'unionallselect'Q',N'囕'unionallselect'R',N'鶸'unionallselect'S',N'蜶'unionallselect'T',N'籜'unionallselect'W',N'鶩'unionallselect'X',N'鑂'unionallselect'Y',N'韻'unionallselect'Z',N'咗')Twhereword>=@wordcollateChinese_PRC_CS_AS_KS_WSorderbyPYASC)else@wordend)set@str=right(@str,len(@str)-1)endreturn@PYend
--函数调用实例:selectdbo.fun_getPY('中华人民共和国'),dbo.fun_getPY('中華人民共和國')结果都为:ZHRMGHG