今天需要修改機器A中的sql server2008 R2的表里一個姓名字段,於是直接select * from tableName where name='張三',發現雖然表中有這個張三的記錄,但是卻查不出來,於是換一個機器B新建一個同類型的nvarchar字段一試可以查出,想想估計是字符集出問題了,查看B中的字符集是Chinese_PRC_CI_AS,查看A是Latin1_General_CI_AS,於是搜索“sqlserver 字符集 查詢中文”關鍵字,遂找到可以使用select * from tableName where name=N'張三'這種形式查詢,一試果然,於是搜索其中詳細信息,得如下一篇,遂寫一博記之:
1. 字符集是支持雙字節的字符集如中文字符集(Collation name為Chinese_PRC_CI_AS)
<1>. 定義varchar(2)
(1) 正式表
總結:在中文字符集下,定義varchar(x),
不論使用不使用N'',英文字符都占1個字節,即可以存x個英文字符;
不論使用不使用N'',中文字符都占2個字節,即可以存(x / 2)個中文,select結果為漢字本身,不是亂碼;
(2) 臨時表
總結:在中文字符集下,定義varchar(x),
和正式表表現一樣;
<2>. 定義nvarchar(2)
(1) 正式表
總結:在中文字符集下,定義nvarchar(x),
不論使用不使用N'',英文字符都占2個字節,即可以存x個英文字符;
不論使用不使用N'',中文字符都占2個字節,即可以存x個中文,select結果為漢字本身,不是亂碼;
(2) 臨時表
總結:在中文字符集下,定義nvarchar(x),
和正式表表現一樣;
<3>. 類型為varchar時,長度 x 和 datalength()對應,都指字節大小;
英文len() = datalength();
中文len() = datalength() / 2;
類型為nvarchar時,長度 x 和 len()對應,都指字符長度;
2. 字符集是支持單字節的字符集如拉丁字符集(Collation name為Latin1_General_CI_AS)
<1>. 定義varchar(2)
(1) 正式表
總結:在英文字符集下,定義varchar(x),
不論使用不使用N'',英文字符都占1個字節,即可以存x個英文字符;
不論使用不使用N'',中文字符都占1個字節,即可以存x個中文,但只保存前半截中文編碼,所以select結果為亂碼;
(特殊:如果使用N'',此時插入的字符數最大為4000)
英文和中文 len() = datalength();
(2) 臨時表
總結:在英文字符集下,定義varchar(x),
不論使用不使用N'',英文字符都占1個字節,即可以存x個英文字符;
不使用N''時,中文占1個字節,可以存x個漢字,但都只存入漢字前半截字符編碼,顯示為亂碼;
使用N''時,中文占2個字節,只可以存 x/2 個漢字,沒有亂碼,取出仍為漢字,說明在英文字符集下通過使用N''是可以保存漢字的;
除用N''保存的中文外,其余英文和中文 len() = datalength();
用N''保存的中文字符len() = datalength() / 2;
<2>. 定義nvarchar(2)
(1) 正式表
總結:在英文字符集下,定義nvarchar(x),
不論使用不使用N'',英文字符都占2個字節,即可以存x個英文字符;(注意每個字符比varchar用的空間大)
不論使用不使用N'',中文字符都占2個字節,即可以存x個中文字符,
但不使用N''只保存前半截中文編碼,所以select結果為亂碼;
使用N''則保存和取出都為漢字本身;
(2) 臨時表
總結:在英文字符集下,定義nvarchar(x),
和正式表表現相同;
<3>. 類型為varchar時,長度 x 和 datalength()對應,都指字節大小;
(臨時表中N''中文字符長度比較特殊;)
類型為nvarchar時,長度 x 和 len()對應,都指字符長度;
二、 使用歸類
拋開不常用的臨時表不談,只看正式表,再加上varchar和nvarchar類型的最大長度,得到以下經驗:
<1> 最大長度問題
1. 在中文字符集下使用varchar,最大長度可定義8000,這個8000是指字節數(datalength()),即最大可以保存8000個英文字符,4000個中文字符;
特殊:若存入字符N'a',則最大能保存4000個字符,但其所占空間為4000字節;
2. 在中文字符集下使用nvarchar,最大長度可定義4000,這個4000是指字符個數(len()),即最大可以保存4000個英文字符,4000個中文字符;
3. 在英文字符集下使用varchar,最大長度可定義8000,這個8000是指字節數(datalength()),由於中文英文都保存為1字節,故最大可以保存8000個英文、中文字符;
4. 在英文字符集下使用nvarchar,最大長度可定義4000,這個4000是指字符個數(len()),即最大可以保存4000個英文字符,4000個中文字符;
<2> 文字顯示問題
1. N''要和數據類型nvarchar, nchar一起使用,如果對varchar, char字段類型強制使用N'',則會產生一些特殊現象,甚至無法控制;
2. 在英文字符集下,想要保存特殊符號字符、中文等雙字節字符,在定義表結構時要使用nvarchar或者nchar,在保存時要用N'';
3. 在中文字符集下,數據庫系統缺省已經可以保存特殊符號字符、中文等雙字節字符。即使用不使用N'',都按雙字節處理。但為了統一期間建議:
在定義表結構時如果使用nvarchar或者nchar,在保存時要用N'',
在定義表結構時如果使用varchar和char,此時不要使用N''操作;
4. SUBSTRING ( expression , start , length )
length:是一個整數,指定子串的長度(要返回的字符數或字節數)。
中文字符集中按字符數取;
英文字符集中,char, varchar按字節數取,nchar, nvarchar按字符數取;