關於SQL SERVER的N前綴的理解


加N前綴指定后面的字符串為UNICODE常量, SQL Server 的 Unicode 數據類型是基於 SQL-92 標准中的國家字符數據類型。SQL-92 使用前綴字符 N 標識這些數據類型及其值。 
1, Unicode 數據使用 SQL Server 中的 ncharvarcharntext 數據類型進行存儲。對於存1儲來源於多種字符集的字符的列,可采用這些數據類型。當列中各項所包含的 Unicode 字符數不同時(至多為 4000),使用 nvarchar 類型。當列中各項為同一固定長度時(至多為 4000Unicode 字符),使用 nchar 類型。當列中任意項超過 4000 個 Unicode字符時,使用 ntext 類型。

在 Microsoft SQL Server  2000 中,傳統上非 Unicode 數據類型允許使用由特定字符集定義的字符。字符集是在安裝 SQL Server 時選擇的,不能更改。使用 非Unicode 數據類型存儲數據時,如varchar, char, text等,如果未指定字符排序序列時(字符集),使用默認的字符集,即使為某個字段指定了字符排序序列時,如果SQL Server 默認的排序序列與指定字段的排序序列不同時,不加N的話也會產生亂碼,如默認的字符集是單字節的字符集如拉丁字符集(Collation name為Latin1_General_CI_AS)的時候,如果定義Name為Varchar類型,字符集為中文字符集時(Collation name為Chinese_PRC_CI_AS),用如下的插入語句也會亂碼

insert a(name) values ('AA中'),因為數據插入的時候,默認還是用Latin1_General_CI_AS字符集送到服務器,再轉換為Collation name為Chinese_PRC_CI_AS時,產生亂碼,但如果改為如下的時候: insert a(name) values (N'AA中') 則能正確插入,因為通過N前綴,以UNICODE的形式送到SQLSERVER,然后再轉換成Chinese_PRC_CI_AS時,就不會產生亂碼。

2,UNICODE和非UNICODE之間的轉換
2-1 UNICODE--〉非UNICODE:Convert(varchar(50), name Collate Chinese_PRC_CS_AS_KS_WS)--name 是nvarvhar類型的,如name是'AA中'的時候

Select DATALENGTH(Convert(varchar(50), name Collate Chinese_PRC_CS_AS_KS_WS)) from x, 返回的長度為4(UNICODE的時候為6)

2-2 非UNICODE--〉UNICODE的時候:Convert(nvarchar(50), name)--name是varchar類型的時候如name是'AA中'的時候

Select DATALENGTH(Convert(nvarchar(50), name)) from x, 返回的長度為6(非UNICODE的時候為4)

3, 試驗歸類
測試SQL:
------------------------------------------------------------
drop table a
create table a(a varchar(2))

insert into a values('a')
insert into a values(N'a')
insert into a values('深圳')
insert into a values(N'深圳')
select a, len(a), datalength(a) from a

drop table #a
create table a(a varchar(2))

insert into #a values('a')
insert into #a values(N'a')
insert into #a values('深圳')
insert into #a values(N'深圳')
select a, len(a), datalength(a) from #a

------------------------------------------------------------
drop table a
create table a(a varchar(8000))

insert into a select REPLICATE('a', 8000) 
insert into a select REPLICATE('', 8000) 
insert into a select REPLICATE(N'a', 8000) 
insert into a select REPLICATE(N'', 8000) 
select a, len(a), datalength(a) from a


3-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()對應,都指字符長度; 
    
3-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()對應,都指字符長度; 

4、 使用歸類
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按字符數取;

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM