1. 程式人生 > >SQLServer特殊字元/生僻字與varchar

SQLServer特殊字元/生僻字與varchar

對於中文版的SQL SERVER,預設安裝後使用的預設排序規則為Chinese_PRC_CI_AS,在此排序規則下,使用varchar型別來可以“正常存取”存放中文字元以及一些東南亞國家的字元,同時varchar型別在存放英文字元和數字時比nvarchar節省一半的儲存空間,因此很多DBA都習慣使用varchar型別來存放字元資料,但這樣便存在一些亂碼隱患!

首先是特殊字元如上下標或版權字元,測試Code如下:

--準備測試表
DROP TABLE TB1
GO
CREATE TABLE TB1
(
C1 VARCHAR(200),
C2 NVARCHAR(200)
)
GO
--插入測試資料
INSERT INTO TB1(C1,C2)
SELECT N'm²',N'm²'
UNION
SELECT N'®',N'®'
--查詢
SELECT C1,
CAST(C1 AS NVARCHAR(200)) AS C1_N,
C2,
CAST(C2 AS VARCHAR(200)) AS C2_V
FROM  TB1

可以明顯地看到上標在varchar型別下轉換成普通數字2,而版權符號在varchar型別下直接就亂碼。

對於這些特殊字元,可能不會被使用到,比如使用者姓名欄位,那麼是不是就可以使用varchar型別了呢?

當然不是,能避開特殊字元,還得考慮“有文化的父母”給子女來點生僻字以展示有文化!!!比如五代十國中南漢的建立者劉龑就自認為很牛叉,於是自己創了一個“龑”字,取意為飛龍在天,如此牛叉的意義就不招varchar的“喜歡”,測試code如下:測試結果如下:

 

 

可以明顯地看到上標在varchar型別下轉換成普通數字2,而版權符號在varchar型別下直接就亂碼。

對於這些特殊字元,可能不會被使用到,比如使用者姓名欄位,那麼是不是就可以使用varchar型別了呢?

當然不是,能避開特殊字元,還得考慮“有文化的父母”給子女來點生僻字以展示有文化!!!比如五代十國中南漢的建立者劉龑就自認為很牛叉,於是自己創了一個“龑”字,取意為飛龍在天,如此牛叉的意義就不招varchar的“喜歡”,測試code如下:

INSERT INTO TB1(C1,C2)
SELECT N'劉龑',N'劉龑'
 
SELECT C1,
CAST(C1 AS NVARCHAR(200)) AS C1_N,
C2,
CAST(C2 AS VARCHAR(200)) AS C2_V
FROM  TB1

顯示結果如下:

“龑”字只能在NVARCHAR模式下才能完好地顯示哈!

建議使用NVARCHAR來存放非英文字元資料理由:
理由1:VARCHAR型別存放特殊字元或生僻字時存在亂碼或字元被轉變的問題
理由2:對於中文字元,使用VARCHAR和NVARCHAR消耗同樣的空間,對於英文字元,使用VARCHAR比NVARCHAR節省一倍的空間,但隨著磁碟成本越來越低,其提升的效能和節省的成本有限。(例外:如果資料中存在大量英文字元和少量非英文字元,則可以考慮VARCHAR型別)
理由3:對於需要國際化的企業,後期將VARCHAR升級為NVARCHAR的成本太高或難以實現
理由4:使用VARCHAR存放非英文字元時,容易生成錯誤的預估值,尤其在執行LIKE這類字首匹配的預估時。顯示結果如下: 

“龑”字只能在NVARCHAR模式下才能完好地顯示哈!
建議使用NVARCHAR來存放非英文字元資料理由:
理由1:VARCHAR型別存放特殊字元或生僻字時存在亂碼或字元被轉變的問題
理由2:對於中文字元,使用VARCHAR和NVARCHAR消耗同樣的空間,對於英文字元,使用VARCHAR比NVARCHAR節省一倍的空間,但隨著磁碟成本越來越低,其提升的效能和節省的成本有限。(例外:如果資料中存在大量英文字元和少量非英文字元,則可以考慮VARCHAR型別)
理由3:對於需要國際化的企業,後期將VARCHAR升級為NVARCHAR的成本太高或難以實現
理由4:使用VARCHAR存放非英文字元時,容易生成錯誤的預估值,尤其在執行LIKE這類字首匹配的預估時。