前言
前面幾篇文章我們講解了索引有關(guān)知識,這一節(jié)我們再繼續(xù)我們下面內(nèi)容講解,簡短的內(nèi)容,深入的理解。
數(shù)據(jù)類型
SQL Server支持兩種字符數(shù)據(jù)類型,一種是常規(guī),另外一種則是Unicode。常規(guī)數(shù)據(jù)類型包括CHAR和VARCHAR,Unicode數(shù)據(jù)類型包括NCAHR和NVARCHAR。常規(guī)字符的每個字符使用1個字節(jié)存儲,而Unicode數(shù)據(jù)的每個字符要求2個字節(jié)。常規(guī)字符列限制為僅僅只針對于英語,而Unicode則是針對于多種語言。兩種字符數(shù)據(jù)類型的文本表示方式也不相同,在表示常規(guī)字符文本時,只需要使用單引號,比如'Hello,my name is JeffckyWang,I'm from cnblogs',而對于Unicode字符文本時,需要指定字符N作為前綴,即N‘Hello,my name is JeffckyWang,I'm from cnblogs'。
名稱中沒有VAR元素的任何數(shù)據(jù)類型(CHAR、NCHAR)具有固定長度,即SQL Server按照列定義大小保留行空間,而不是按照字符中的實際字符保留空間。比如某列定義大小為CHAR(25),則SQL Server在該行保留25個字符的空間,而不管存儲字符串的長度。
名稱中含有VAR元素的數(shù)據(jù)類型(VARCHAR、NVARCHAR)具有可變長度,即SQL Server根據(jù)存儲需要,在行中使用盡可能多的存儲空間存儲字符串,同時外加兩個額外的字節(jié)偏移數(shù)據(jù)。例如,如果將某列定義為VARCHAR(25),此時支持的最大字符數(shù)為25,但實際上按照字符串中實際字符確定存儲量。-摘抄自SQL Server 2012 T-SQL基礎(chǔ)教程。
這里關(guān)于Unicode字符數(shù)據(jù)類型我們需要重點理解下。我們先創(chuàng)建一個表,如下:
CREATE TABLE UnicodeType
(
firstname VARCHAR(5) NOT NULL,
lastname NVARCHAR(5) NOT NULL
);
此時我們手動插入數(shù)據(jù),正常插入,如下:
INSERT dbo.UnicodeType
( firstname, lastname )
VALUES ( '11111', -- firstname - varchar(5)
N'啊的發(fā)個好' -- lastname - nvarchar(5)
)
字符都完全插入表中,如下:
此時我們將firstname,插入五個中文試試如下:
INSERT dbo.UnicodeType
( firstname, lastname )
VALUES ( '達(dá)得到讓人', -- firstname - varchar(5)
N'達(dá)得到讓人' -- lastname - nvarchar(5)
)
此時出現(xiàn)如下結(jié)果:
也就是說在常規(guī)字符類型如上述VARVHAR中定義為五個字符,此時我們插入五個中文字符則會被截取,當(dāng)然也插入不進(jìn)去。因為上述已經(jīng)明確講了1個非英語字符串相當(dāng)于兩個字節(jié),此時中文所占用的是十個字節(jié),而此時VARCHAR才五個字符,所以出現(xiàn)警告。我們再來將firstname插入兩個中文兩個英文或者數(shù)字看看
INSERT dbo.UnicodeType
( firstname, lastname )
VALUES ( '達(dá)得1', -- firstname - varchar(5)
N'達(dá)得到讓人' -- lastname - nvarchar(5)
)
此時插入進(jìn)去為出現(xiàn)警告,因為此時兩個中文字符即四個字節(jié)加上一個數(shù)字字節(jié)剛好五個字節(jié),所以能正常插入,我們再來看看lastname,由上知,既然英文或者數(shù)字被當(dāng)做一個字節(jié),那么我們對lastname插入四個中文字符和兩個英文字節(jié)剛好十個字節(jié)應(yīng)該是好使的。我們看看:
INSERT dbo.UnicodeType
( firstname, lastname )
VALUES ( '達(dá)得1', -- firstname - varchar(5)
N'達(dá)得到讓ab' -- lastname - nvarchar(5)
)
oh,shit,此時居然出錯了,如下:
我們上述分析的不是有理有據(jù)么,難道這里英文不是占用一個字節(jié)么,我們插入一個英文試試。
INSERT dbo.UnicodeType
( firstname, lastname )
VALUES ( '達(dá)得1', -- firstname - varchar(5)
N'達(dá)得到讓b' -- lastname - nvarchar(5)
)
結(jié)果正確了,實踐是檢驗真理的唯一標(biāo)準(zhǔn),從這里我們可以看出:在常規(guī)字符中,一個中文會當(dāng)做是兩個字節(jié)來使用,一個英文會當(dāng)做是一個字節(jié)使用,但是在Unicode中,一個中文也是會當(dāng)做兩個字節(jié)來使用,但是一個英文也會當(dāng)做是兩個字節(jié)來使用。至此我們可以得出結(jié)論,個人一直以為在Unicode中,將英文是作為一個字節(jié)存儲,見識短啊。
常規(guī)字符和Unicode中一個中文字符用兩個字節(jié)存儲,而對英文,常規(guī)字符用一個字節(jié)存儲,而Unicode依然是用兩個字節(jié)存儲。
字符串函數(shù)
對字符串操作的函數(shù)有SUBSTRING、LEFT、RIGHT、CHARINDEX、PATINDEX、REPLACE、REPICATE、STUFF、UPPER、LOWER、RTRIM、LTRIM、FORMAT。對于簡單的函數(shù)我們略過,下面我們來講講幾個需要注意的地方。
LEN與DATALENGTH比較
我們首先創(chuàng)建如下測試表
CREATE TABLE StringFun
(
firststr VARCHAR(max) NOT NULL,
secondstr TEXT NOT NULL
);
我們插入測試數(shù)據(jù)
INSERT dbo.StringFun
( firststr, secondstr )
VALUES ( '我是JeffckyWang,我來自于博客園,專注于.NET技術(shù)', -- firststr - varchar(max)
'我是JeffckyWang,我來自于博客園,專注于.NET技術(shù)' -- secondstr - text
)
我們首先利用LEN函數(shù)來返回firststr和secondstr的字符串長度大小
SELECT LEN(firststr) AS VARCAHRFieldSize
FROM dbo.StringFun
SELECT LEN(secondstr) AS TEXTFieldSize
FROM dbo.StringFun
好極了,出錯了。LEN函數(shù)無法對TEXT進(jìn)行操作。我們接著往下看。
SELECT DATALENGTH(firststr) AS VARCAHRFieldSize
FROM dbo.StringFun
SELECT DATALENGTH(secondstr) AS TEXTFieldSize
FROM dbo.StringFun
此時未報錯誤,結(jié)果顯示為47個字節(jié)大小。 既然LEN對文本無效,我們不對文本操作就是。
SELECT LEN(firststr) AS VARCAHRFieldSize
FROM dbo.StringFun
SELECT DATALENGTH(secondstr) AS TEXTFieldSize
FROM dbo.StringFun
此時類型為VARCAHR的firststr字節(jié)大小卻為31,為何,看到這里我們想必恍然大悟,在上述我們講到常規(guī)字符會對中文以一個字符兩個字節(jié)大小存儲,但是這里實際上返回的是實際字符大小,當(dāng)然一個是存儲,一個是檢索,還是有點不同,同時我們也不會將中文存儲到VARCHAR中。到這里我們可以得出結(jié)論。
結(jié)論:DATALENGTH函數(shù)是針對于TEXT,而LEN是針對于VARCHAR,對TEXT無效會報錯。
到這里我們還有一個特殊值未進(jìn)行處理,那就是NULL。那么問題來了,LEN和DATALENGTH對NULL,它的長度大小是多少呢,是0還是不是0尼?
是我們來測試下:
DECLARE @MyVar VARCHAR(10)
SET @MyVar = NULL
IF (LEN(@MyVar) = 0)
PRINT 'LEN of NULL is 0'
ELSE
PRINT 'LEN of NULL is NULL'
我們上述得到的結(jié)果是LEN of NULL is NULL,DATALENGTH就不再演示了。
結(jié)論:LEN和DATALENGTH對于NULL計算的結(jié)果就是NULL。
我們再來看看二者差異的一個小地方:
SELECT LEN('JeffckyWang ') AS 'LEN'
SELECT DATALENGTH('JeffckyWang ') AS 'DATALENGTH'
結(jié)論:LEN會刪除尾隨空格,而DATALENGTH不會
CHARINDEX與PATINDEX比較
CHARINDEX和PATINDEX字符串函數(shù)都是查詢返回指定匹配字符串的開始位置。
我們先查詢一個字符串,此字符串在表中存在,如下:
USE AdventureWorks2012;
GO
SELECT CHARINDEX('Worn', DocumentSummary) AS 'CHARINDEX'
FROM Production.Document
WHERE ChangeNumber = 55;
GO
SELECT PATINDEX('Worn', DocumentSummary) AS 'PATINDEX'
FROM Production.Document
WHERE ChangeNumber = 55;
為何CHARINDEX函數(shù)查找到了,而PATINDEX沒有查詢到呢?此時就說說二者的區(qū)別,二者都有兩個參數(shù),第二個參數(shù)都是要匹配的字符串,但是PATINDEX函數(shù)必須在需要匹配的字符串之前或者之后添加百分號即通配符,而CHARINDEX函數(shù)則不需要。如下即可:
USE AdventureWorks2012;
GO
SELECT CHARINDEX('Worn', DocumentSummary) AS 'CHARINDEX'
FROM Production.Document
WHERE ChangeNumber = 55;
GO
SELECT PATINDEX('%Worn%', DocumentSummary) AS 'PATINDEX'
FROM Production.Document
WHERE ChangeNumber = 55;
結(jié)論:PATINDEX匹配字符串必須在字符串前面或者后面或者前后添加通配符,而CHARINDEX無需添加。
總結(jié)
本節(jié)我們主要講解了SQL中的數(shù)據(jù)類型以及幾個需要注意的地方,簡短的內(nèi)容,深入的理解,我們下節(jié)再會。
以上就是本文的全部內(nèi)容,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,同時也希望多多支持腳本之家!
您可能感興趣的文章:- 詳解MySQL數(shù)據(jù)類型int(M)中M的含義
- mysql存儲引擎和數(shù)據(jù)類型(二)
- Java數(shù)據(jù)類型與MySql數(shù)據(jù)類型對照表
- SQL Server數(shù)據(jù)類型轉(zhuǎn)換方法
- SQL Server比較常見數(shù)據(jù)類型詳解
- SQLite教程(七):數(shù)據(jù)類型詳解
- SQL Server數(shù)據(jù)類型char、nchar、varchar、nvarchar的區(qū)別淺析
- sql使用cast進(jìn)行數(shù)據(jù)類型轉(zhuǎn)換示例
- SQL2005中char nchar varchar nvarchar數(shù)據(jù)類型的區(qū)別和使用環(huán)境講解
- SQL的常用數(shù)據(jù)類型列表詳解