校勘(collation)是指對代碼頁、字母大小寫、音調(diào)、語言和字母表的整理,很多?倍际窃跀(shù)據(jù)進(jìn)入數(shù)據(jù)庫之前進(jìn)行的,根據(jù)我的經(jīng)驗(yàn),北美的大部分?jǐn)?shù)據(jù)庫管理員都在使用默認(rèn)的大小寫敏感的?痹O(shè)定,這對于數(shù)據(jù)本身沒有影響,但是對于數(shù)據(jù)的比較和索引會造成影響。
這篇文章將向您介紹一些相關(guān)的?狈椒ǎ约皵(shù)據(jù)庫對多種字符集的處理方法。
為了說明?钡氖褂茫覀兪紫葋韯(chuàng)建一個(gè)數(shù)據(jù)庫,列表A給出了創(chuàng)建數(shù)據(jù)庫的代碼。
CREATE SCHEMA CaseCheck
GO
CREATE TABLE CaseCheck.Names
(
NamePK Int Identity(1,1) PRIMARY KEY,
Name Varchar(50) NOT NULL
)
GO
INSERT INTO CaseCheck.Names VALUES (''Fuller'')
INSERT INTO CaseCheck.Names VALUES (''FuLLer'')
INSERT INTO CaseCheck.Names VALUES (''FULLER'')
INSERT INTO CaseCheck.Names VALUES (''fuller'')
GO
列表A
列表B是一些查詢,對于大小寫不敏感的情況,這幾個(gè)查詢將返回相同的四個(gè)數(shù)據(jù)行,但是如果我們的任務(wù)是從數(shù)據(jù)行中選取大小寫完全匹配的記錄呢?
SELECT * FROM CaseCheck.Names
SELECT * FROM CaseCheck.Names WHERE Name = ''fuller''
SELECT * FROM CaseCheck.Names WHERE Name = ''FULLER''
SELECT * FROM CaseCheck.Names WHERE Name = ''fuller''
GO
列表 B
現(xiàn)在我們就要使用?钡墓δ芰,盡管在數(shù)據(jù)庫創(chuàng)建的時(shí)候,數(shù)據(jù)庫管理員已經(jīng)指定了?钡倪x項(xiàng),但是您可以通過WHERE語句中的COLLATE選項(xiàng)來使用不同的?痹O(shè)定,在列表C的查詢中,前三個(gè)都返回了一條記錄,而最后一個(gè)查詢的返回結(jié)果為空。
SELECT * FROM CaseCheck.Names WHERE Name = ''fuller''
COLLATE Latin1_General_CS_AS
SELECT * FROM CaseCheck.Names WHERE Name = ''FULLER''
COLLATE Latin1_General_CS_AS
SELECT * FROM CaseCheck.Names WHERE Name = ''fuller''
COLLATE Latin1_General_CS_AS
SELECT * FROM CaseCheck.Names WHERE Name = ''FUllER''
COLLATE Latin1_General_CS_AS
GO
列表 C
假設(shè)您現(xiàn)在想把所有''fuller''形式的拼寫改為''Fuller''(包括像''fUlLEr''這種毫無意義的拼寫組合),通過列表D中的代碼,您可以非常輕松地實(shí)現(xiàn)這一功能。
UPDATE CaseCheck.NamesSET Name = UPPER(LEFT(Name,1))
+ LOWER(SUBSTRING(Name,2,LEN(Name)-1))
列表D
從大型主機(jī)上導(dǎo)入數(shù)據(jù)的時(shí)候,我都會首先運(yùn)行以上的代碼,這樣就不必再擔(dān)心單詞大小寫的問題了。
如果您想查看所有的?边x項(xiàng)及其簡要說明,可以運(yùn)行以下的SQL代碼:SELECT * FROM ::fn_helpcollations()。
想要查看數(shù)據(jù)庫當(dāng)前的?痹O(shè)定,可以使用以下代碼:
SELECT collation_name
FROM master.sys.databases
WHERE Name=''SQLTips''
在列表E中,我添加了一些帶有特殊字符的數(shù)據(jù)行,我使用了我的好朋友DejanSunderic的名字,他的名字應(yīng)該拼寫為?underic''(字母c實(shí)際上應(yīng)該有重音符號的,由于使用的字體,所以顯示成了現(xiàn)在的效果)。
INSERT INTO CaseCheck.Names VALUES
(NChar(352)+ ''underi'' + NChar(263))
INSERT INTO CaseCheck.Names VALUES
(''SUNDERIC'')
INSERT INTO CaseCheck.Names VALUES
(''sUnDeRI'' + Nchar(263))
INSERT INTO CaseCheck.Names VALUES
(''Sunderi'' + Nchar(263))
GO
列表 E
如果不使用COLLATE,那么會發(fā)生非常有意思的事情,運(yùn)行一下的查詢語句:
SELECT *
FROM CaseCheck.Names
WHERE Name LIKE N''S%''
您得到的結(jié)果是:
NamePK Name
6 SUNDERIC
7 sUnDeRIc
8 Sunderic
注意,帶有特殊字符的''?underic''并沒有被包含在內(nèi),
讓我們再來看看另外一個(gè)實(shí)驗(yàn):
SELECT * FROM CaseCheck.Names
ORDER BY Name
運(yùn)行此查詢的結(jié)果如下:
NamePK Name
5 ?underic
1 Fuller
2 FuLLer
3 FULLER
4 fuller
6 SUNDERI
7 sUnDeRIc
這里有很明顯的錯(cuò)誤,PK5應(yīng)當(dāng)位于''Fuller''之后,我不是語言專家,因此不知道它應(yīng)該位于Ss的什么位置,但是我覺得這是本地規(guī)則造成的結(jié)果,很明顯,''?underic''應(yīng)該出現(xiàn)在所有的''Fuller''之后,而不是在''Fuller''前面。
我還進(jìn)行了另外一項(xiàng)實(shí)驗(yàn),使用西里爾字母來拼寫我的好朋友Alexander Karmanov的名字,在圖片A中您可以看到西里爾字母的拼寫,我運(yùn)行了圖片B所示的語句來添加這條記錄。
圖片A
圖片B
圖片C
使用默認(rèn)的字符集,此查詢將會返回一系列問號,如果您想得到正確的結(jié)果,那么必須需要使用數(shù)據(jù)庫可以接受的Unicode字符集,參見圖片C。
如果您想確認(rèn)一個(gè)給定數(shù)據(jù)庫中使用的初始?,可以使以下的代碼:
SELECT collation_name
FROM master.sys.databases
WHERE Name = "SQLTips"