国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 開發 > 綜合 > 正文

用排序規則特點計算漢字筆劃和取得拼音首字母

2024-07-21 02:11:58
字體:
來源:轉載
供稿:網友
 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<b.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   a.code<b.code    
  where   b.code   is   null  
  order   by   a.id  
  --再加最后四個漢字  
  set   identity_insert   tab_hzbh   on  
  go  
  insert   tab_hzbh(id,cnword)  
       select   35,n'齾'  
  union   all   select   36,n'齉'  
  union   all   select   39,n'靐'  
  union   all   select   64,n'龘'  
  go  
  set   identity_insert   tab_hzbh   off  
  go  
   
    到此為止,我們可以得到結果了,比如我們想得到漢字“國”的筆劃:  
   
  declare   @a   nchar(1)  
  set   @a='國'  
  select   top   1   id    
  from     tab_hzbh    
  where   cnword>[email protected]   collate   chinese_prc_stroke_cs_as_ks_ws  
  order   by   id  
   
  id                      
  -----------    
  8  
  (結果:漢字“國”筆劃數為8)  
   
    上面所有準備過程,只是為了寫下面這個函數,這個函數撇開上面建的所有臨時表和固  
  定表,為了通用和代碼轉移方便,把表tab_hzbh的內容寫在語句內,然后計算用戶輸入一串  
  漢字的總筆劃:  
   
  create   function   fun_getbh(@str   nvarchar(4000))  
  returns   int  
  as  
  begin  
  declare   @word   nchar(1),@n   int  
  set   @n=0  
  while   len(@str)>0  
  begin  
  set   @word=left(@str,1)  
  --如果非漢字,筆劃當0計  
  set   @[email protected]+(case   when   unicode(@word)   between   19968   and   19968+20901  
  then   (select   top   1   id   from   (  
  select   1   as   id,n'亅'   as   word    
  union   all   select   2,n'阝'    
  union   all   select   3,n'馬'    
  union   all   select   4,n'風'    
  union   all   select   5,n'龍'    
  union   all   select   6,n'齊'    
  union   all   select   7,n'龜'    
  union   all   select   8,n'齒'    
  union   all   select   9,n'鴆'    
  union   all   select   10,n'齔'    
  union   all   select   11,n'龕'    
  union   all   select   12,n'龂'    
  union   all   select   13,n'齠'    
  union   all   select   14,n'齦'    
  union   all   select   15,n'齪'    
  union   all   select   16,n'龍'    
  union   all   select   17,n'龠'    
  union   all   select   18,n'龎'    
  union   all   select   19,n'龐'    
  union   all   select   20,n'龑'    
  union   all   select   21,n'龡'    
  union   all   select   22,n'龢'    
  union   all   select   23,n'龝'    
  union   all   select   24,n'齹'    
  union   all   select   25,n'龣'    
  union   all   select   26,n'龥'    
  union   all   select   27,n'齈'    
  union   all   select   28,n'龞'    
  union   all   select   29,n'麷'    
  union   all   select   30,n'鸞'    
  union   all   select   31,n'麣'    
  union   all   select   32,n'龖'    
  union   all   select   33,n'龗'    
  union   all   select   35,n'齾'    
  union   all   select   36,n'齉'    
  union   all   select   39,n'靐'    
  union   all   select   64,n'龘'    
  )   t    
  where   word>[email protected]   collate   chinese_prc_stroke_cs_as_ks_ws  
  order   by   id   asc)   else   0   end)  
  set   @str=right(@str,len(@str)-1)  
  end  
  return   @n  
  end  
   
  --函數調用實例:  
  select   dbo.fun_getbh('中華人民共和國'),dbo.fun_getbh('中華人民共和國')  
     
    執行結果:筆劃總數分別為39和46,簡繁體都行。  
————————————————————————————————————————

當然,你也可以把上面“union all”內的漢字和筆劃改存在固定表內,在漢字  
  列建clustered   index,列排序規則設定為:  
        chinese_prc_stroke_cs_as_ks_ws  
  這樣速度更快。如果你用的是big5碼的操作系統,你得另外生成漢字,方法一樣。  
  但有一點要記住:這些漢字是通過sql語句select出來的,不是手工輸入的,更不  
  是查字典得來的,因為新華字典畢竟不同于unicode字符集,查字典的結果會不正  
  確。  
   
      
                          用排序規則的特性得到漢字拼音首字母  
   
    用得到筆劃總數相同的方法,我們也可以寫出求漢字拼音首字母的函數。如下:  
   
  create   function   fun_getpy(@str   nvarchar(4000))  
  returns   nvarchar(4000)  
  as  
  begin  
  declare   @word   nchar(1),@py   nvarchar(4000)  
  set   @py=''  
  while   len(@str)>0  
  begin  
  set   @word=left(@str,1)  
  --如果非漢字字符,返回原字符  
  set   @[email protected]+(case   when   unicode(@word)   between   19968   and   19968+20901  
  then   (select   top   1   py   from   (  
  select   'a'   as   py,n'驁'   as   word  
  union   all   select   'b',n'簿'  
  union   all   select   'c',n'錯'  
  union   all   select   'd',n'鵽'  
  union   all   select   'e',n'樲'  
  union   all   select   'f',n'鰒'  
  union   all   select   'g',n'腂'  
  union   all   select   'h',n'夻'  
  union   all   select   'j',n'攈'  
  union   all   select   'k',n'穒'  
  union   all   select   'l',n'鱳'  
  union   all   select   'm',n'旀'  
  union   all   select   'n',n'桛'  
  union   all   select   'o',n'漚'  
  union   all   select   'p',n'曝'  
  union   all   select   'q',n'囕'  
  union   all   select   'r',n'鶸'  
  union   all   select   's',n'蜶'  
  union   all   select   't',n'籜'  
  union   all   select   'w',n'鶩'  
  union   all   select   'x',n'鑂'  
  union   all   select   'y',n'韻'  
  union   all   select   'z',n'咗'  
  )   t    
  where   word>[email protected]   collate   chinese_prc_cs_as_ks_ws    
  order   by   py   asc)   else   @word   end)  
  set   @str=right(@str,len(@str)-1)  
  end  
  return   @py  
  end  
   
  --函數調用實例:  
  select   dbo.fun_getpy('中華人民共和國'),dbo.fun_getpy('中華人民共和國')  
  結果都為:zhrmghg  
   
        你若有興趣,也可用相同的方法,擴展為得到漢字全拼的函數,甚至還可以得到全拼的讀  
  音聲調,不過全拼分類大多了。得到全拼最好是用對照表,兩萬多漢字搜索速度很快,用對照  
  表還可以充分利用表的索引。  
          排序規則還有很多其它的巧妙用法,限于篇幅在此就不再詳細說明。歡迎大家共同探討。

————————————————————————————————————

以下是用pl/sql寫的:



create or replace function fun_getpy(str varchar2)
returns varchar2
as

word char(1);
py varchar2(4000):='';

begin
while length(str)>0 loop
word:=lpad(str,1);
py:=py+(case when unicode(word) between 19968 and 19968+20901
then (select py from (select * from (
select 'a' as py,n'驁' as word
union all select 'b',n'簿'
union all select 'c',n'錯'
union all select 'd',n'鵽'
union all select 'e',n'樲'
union all select 'f',n'鰒'
union all select 'g',n'腂'
union all select 'h',n'夻'
union all select 'j',n'攈'
union all select 'k',n'穒'
union all select 'l',n'鱳'
union all select 'm',n'旀'
union all select 'n',n'桛'
union all select 'o',n'漚'
union all select 'p',n'曝'
union all select 'q',n'囕'
union all select 'r',n'鶸'
union all select 's',n'蜶'
union all select 't',n'籜'
union all select 'w',n'鶩'
union all select 'x',n'鑂'
union all select 'y',n'韻'
union all select 'z',n'咗'
) t order by py asc)
where rownum <2 and word>=word collate chinese_prc_cs_as_ks_ws
) else word end)
str:=rpad(str,length(str)-1);
end loop;
return py;
end fun_getpy;

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 会泽县| 龙泉市| 五大连池市| 会东县| 饶阳县| 西丰县| 信丰县| 阳谷县| 宽城| 许昌市| 宁城县| 富顺县| 东宁县| 越西县| 德令哈市| 建宁县| 平陆县| 那曲县| 东安县| 肥西县| 文山县| 简阳市| 阿拉善左旗| 镇平县| 延安市| 开化县| 云阳县| 双鸭山市| 靖西县| 顺平县| 新化县| 思南县| 新巴尔虎右旗| 东丽区| 太白县| 湄潭县| 张北县| 临泉县| 日喀则市| 曲阜市| 丹阳市|