理解collate Chinese_PRC_CI_AS

 

咱們在create table時常常會碰到這樣的語句,例如:password nvarchar(10)collate chinese_prc_ci_as null,那它究竟是什麼意思呢?不妨看看下面:sql

首先,collate是一個子句,可應用於數據庫定義或列定義以定義排序規則,或應用於字符串表達式以應用排序規則投影。數據庫

語法是collate collation_namewindows

collation_name ::={windows_collation_name}|{sql_collation_name}服務器

參數collate_name是應用於表達式、列定義或數據庫定義的排序規則的名稱。collation_name 能夠只是指定的 Windows_collation_name SQL_collation_nameide

Windows_collation_name Windows 排序規則的排序規則名稱。參見 Windows 排序規則名稱。 SQL_collation_name SQL 排序規則的排序規則名稱。參見 SQL 排序規則名稱。函數

下面簡單介紹一下排序規則:測試

什麼叫排序規則呢?MS是這樣描述的:" Microsoft SQL Server 2000 中,字符串的物理存儲由排序規則控制。排序規則指定表示每一個字符的位模式以及存儲和比較字符所使用的規則。"   在查詢分析器內執行下面語句,能夠獲得SQL SERVER支持的全部排序規則。spa

    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的排序規則平時使用不是不少,也許很多初學者還比較陌生,但有 一個錯誤你們應是常常碰到: 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 A.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>=@a 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 @n=@n+(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>=@word 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 @PY=@PY+(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>=@word 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

相關文章
相關標籤/搜索