--
最近溫習了點排序規則的資料,順便整理了下,希望對初學者有所幫助
/*
標 題 :排序规则常見問題整體帖 整理人 :【水族杰纶】(wufeng4552) 時 間 :2009-09-22 13:25:22.247
*/
--
(一)->排序規則概念:
/*
聯機幫助:在Microsoft SQL Server 2000 中,字符串的物理存储由排序规则控制。 排序规则指定表示每个字符的位模式以及存储和比较字符所使用的规则
*/
--
1 查看系统中所支持的全部排序规则列表
select
*
from
::fn_helpcollations()
/*
name description ------------------------------------------------------------------------------------------------------------------------- Albanian_BIN Albanian, binary sort Albanian_CI_AI Albanian, case-insensitive, accent-insensitive, kanatype-insensitive, width-insensitive ...............................................................
*/
/*
排序规则名称由两部份构成,前半部份是指本排序规则所支持的字符集.如: 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区分 区分大小写:如果想让比较将大写字母和小写字母视为不等,请选择该选项。 区分重音:如果想让比较将重音和非重音字母视为不等,请选择该选项。如果选择该选项,比较还将重音不同的字母视为不等。 区分假名:如果想让比较将片假名和平假名日语音节视为不等,请选择该选项。 区分宽度:如果想让比较将半角字符和全角字符视为不等,请选择该选项
*/
--
2 查看当前系统的排序规则
select
serverproperty(
'
Collation
'
)
--
3 改变数据库的排序规则(做ALTER之前,要中断所有用户对此数据库的访问)
use
master
go
alter
database
dbname collate Chinese_PRC_CS_AS
--
规则名
--
(二)->排序规则的应用
--
1 常見問題 "无法解决 equal to 操作的排序规则冲突."
--
在跨库多表连接查询时,若两数据库默认字符集不同,系统就会返回上述的错误:
--
案例:
if
object_id
(
'
ta
'
)
is
not
null
drop
table
ta
go
create
table
ta(
[
name
]
varchar
(
10
) collate Albanian_CI_AI_WS)
if
object_id
(
'
tb
'
)
is
not
null
drop
table
tb
go
create
table
tb(
[
name
]
varchar
(
10
) collate Chinese_PRC_CI_AI_WS)
select
*
from
ta ,tb
where
ta.
[
name
]
=
tb.
[
name
]
/*
返回錯誤信息: 訊息 468,層級 16,狀態 9,行 2 無法解析 equal to 作業中 "Chinese_PRC_CI_AI_WS" 與 "Albanian_CI_AI_WS" 之間的定序衝突。 上述错误是因为排序规则不一致造成的
*/
--
要排除这个错误,簡單的方法是表连接时指定它的排序规则
select
*
from
ta ,tb
where
ta.
[
name
]
=
tb.
[
name
]
collate Chinese_PRC_CI_AI_WS
--
2 让表列的内容按拼音排序
if
object_id
(
'
tb
'
)
is
not
null
drop
table
tb
go
create
table
tb(ID
int
identity
,
[
name
]
nvarchar
(
2
))
insert
tb
select
N
'
我
'
insert
tb
select
N
'
们
'
insert
tb
select
N
'
都
'
insert
tb
select
N
'
是
'
insert
tb
select
N
'
中
'
insert
tb
select
N
'
国
'
insert
tb
select
N
'
人
'
select
*
from
tb
order
by
[
name
]
collate Chinese_PRC_CS_AS_KS_WS
/*
ID name ----------- ---- 3 都 6 国 2 们 7 人 4 是 1 我 5 中
*/
--
3 让表列的内容按姓氏笔划排序
if
object_id
(
'
tb
'
)
is
not
null
drop
table
tb
go
create
table
tb(ID
int
identity
,
[
name
]
nvarchar
(
2
))
insert
tb
select
N
'
三
'
union
all
select
N
'
乙
'
union
all
select
N
'
二
'
union
all
select
N
'
一
'
union
all
select
N
'
十
'
select
*
from
tb
order
by
[
name
]
collate Chinese_PRC_Stroke_CS_AS_KS_WS
/*
ID name ----------- ---- 4 一 2 乙 3 二 5 十 1 三
*/
--
4 用排序规则的特性计算汉字笔划
/*
WINDOWS多国汉字,UNICODE目前收录汉字共20902个。简体GBK码汉字UNICODE值从19968开始。 首先,我们先用SQLSERVER方法得到所有汉字
*/
if
object_id
(
'
tempdb..#t
'
)
is
not
null
drop
table
#t
go
select
top
20902
code
=
identity
(
int
,
19968
,
1
)
into
#t
from
syscolumns a,syscolumns b
--
用SELECT语句,让它按笔划排序。
select
code,
nchar
(code)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 乛
*/
/*
从上面的结果,我们可以清楚的看到,一笔的汉字,code是从19968到20101,从小到大排,但到 了二笔汉字的第一个字“丁”,CODE为19969,就不按顺序而重新开始了。有了这结果,我们就可以轻 松的用SQL语句得到每种笔划汉字归类的第一个或最后一个汉字。下面用语句得到最后一个汉字:
*/
if
object_id
(
'
tempdb..#t1
'
)
is
not
null
drop
table
#t1
go
create
table
#t1(id
int
identity
,code
int
,cnword
nvarchar
(
2
))
insert
#t1(code,cnword)
select
code,
nchar
(code)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
/*
cnword ------ 亅 阝 马 风 龙 齐 ...
*/
/*
上面可以看出:“亅”是所有一笔汉字排序后的最后一个字,“阝”是所有二笔汉字排序后的最后一个字......等等. 但同时也发现,从第33个汉字“龗(33笔)”后面的笔划有些乱,不正确。但没关系,比“龗”笔划多的只有四个汉字, 我们手工加上:齾35笔,齉36笔,靐39笔,龘64笔
*/
--
建汉字笔划表(TAB_HZBH):
if
object_id
(
'
tab_hzbh
'
)
is
not
null
drop
table
tab_hzbh
go
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
/*
上面所有准备过程,只是为了写下面这个函数,这个函数撇开上面建的所有临时表和固 定表,为了通用和代码转移方便,把表tab_hzbh的内容写在语句内,然后计算用户输入一串 汉字的总笔划:
*/
if
object_id
(
'
fun_getbh
'
)
is
not
null
drop
function
fun_getbh
go
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
go
--
函数调用实例:
select
dbo.fun_getbh(
'
中华人民共和国
'
),dbo.fun_getbh(
'
中華人民共和國
'
)
/*
----------- ----------- 25 46
*/
--
5 用排序规则的特性得到汉字拼音首字母
if
object_id
(
'
fun_getPY
'
)
is
not
null
drop
function
fun_getPY
go
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
colo
分享到:
评论