SQL Server-數據類型(七)

前言

前面幾篇文章咱們講解了索引有關知識,這一節咱們再繼續咱們下面內容講解,簡短的內容,深刻的理解,Always to review the basics。函數

數據類型

SQL Server支持兩種字符數據類型,一種是常規,另一種則是Unicode。常規數據類型包括CHAR和VARCHAR,Unicode數據類型包括NCAHR和NVARCHAR。常規字符的每一個字符使用1個字節存儲,而Unicode數據的每一個字符要求2個字節。常規字符列限制爲僅僅只針對於英語,而Unicode則是針對於多種語言。兩種字符數據類型的文本表示方式也不相同,在表示常規字符文本時,只須要使用單引號,好比'Hello,my name is JeffckyWang,I'm from cnblogs',而對於Unicode字符文本時,須要指定字符N做爲前綴,即N‘Hello,my name is JeffckyWang,I'm from cnblogs’。測試

名稱中沒有VAR元素的任何數據類型(CHAR、NCHAR)具備固定長度,即SQL Server按照列定義大小保留行空間,而不是按照字符中的實際字符保留空間。好比某列定義大小爲CHAR(25),則SQL Server在該行保留25個字符的空間,而無論存儲字符串的長度。spa

名稱中含有VAR元素的數據類型(VARCHAR、NVARCHAR)具備可變長度,即SQL Server根據存儲須要,在行中使用盡量多的存儲空間存儲字符串,同時外加兩個額外的字節偏移數據。例如,若是將某列定義爲VARCHAR(25),此時支持的最大字符數爲25,但實際上按照字符串中實際字符肯定存儲量。-摘抄自SQL Server 2012 T-SQL基礎教程。code

這裏關於Unicode字符數據類型咱們須要重點理解下。咱們先建立一個表,以下:blog

CREATE TABLE UnicodeType
(
 firstname VARCHAR(5) NOT NULL,
 lastname NVARCHAR(5) NOT NULL
);

此時咱們手動插入數據,正常插入,以下:教程

INSERT dbo.UnicodeType
        ( firstname, lastname )
VALUES  ( '11111', -- firstname - varchar(5)
          N'啊的發個好'  -- lastname - nvarchar(5)
          )

字符都徹底插入表中,以下:索引

此時咱們將firstname,插入五個中文試試以下:字符串

INSERT dbo.UnicodeType
        ( firstname, lastname )
VALUES  ( '達獲得讓人', -- firstname - varchar(5)
          N'達獲得讓人'  -- lastname - nvarchar(5)
          )

此時出現以下結果:博客

也就是說在常規字符類型如上述VARVHAR中定義爲五個字符,此時咱們插入五個中文字符則會被截取,固然也插入不進去。由於上述已經明確講了1個非英語字符串至關於兩個字節,此時中文所佔用的是十個字節,而此時VARCHAR才五個字符,因此出現警告。咱們再來將firstname插入兩個中文兩個英文或者數字看看it

INSERT dbo.UnicodeType
        ( firstname, lastname )
VALUES  ( '達得1', -- firstname - varchar(5)
          N'達獲得讓人'  -- lastname - nvarchar(5)
          )

此時插入進去爲出現警告,由於此時兩個中文字符即四個字節加上一個數字字節恰好五個字節,因此能正常插入,咱們再來看看lastname,由上知,既然英文或者數字被當作一個字節,那麼咱們對lastname插入四個中文字符和兩個英文字節恰好十個字節應該是好使的。咱們看看:

INSERT dbo.UnicodeType
        ( firstname, lastname )
VALUES  ( '達得1', -- firstname - varchar(5)
          N'達獲得讓ab'  -- lastname - nvarchar(5)
          )

oh,shit,此時竟然出錯了,以下:

咱們上述分析的不是有理有據麼,難道這裏英文不是佔用一個字節麼,咱們插入一個英文試試。

INSERT dbo.UnicodeType
        ( firstname, lastname )
VALUES  ( '達得1', -- firstname - varchar(5)
          N'達獲得讓b'  -- lastname - nvarchar(5)
          )

結果正確了,實踐是檢驗真理的惟一標準,從這裏咱們能夠看出:在常規字符中,一箇中文會當作是兩個字節來使用,一個英文會當作是一個字節使用,可是在Unicode中,一箇中文會當作兩個字節來使用,可是一個英文也會當作是兩個字節來使用。至此咱們能夠得出結論,我的一直覺得在Unicode中,將英文是做爲一個字節存儲,見識短啊。

常規字符和Unicode中一箇中文字符用兩個字節存儲,而對英文,常規字符用一個字節存儲,而Unicode依然是用兩個字節存儲。

字符串函數

對字符串操做的函數有SUBSTRING、LEFT、RIGHT、CHARINDEX、PATINDEX、REPLACE、REPICATE、STUFF、UPPER、LOWER、RTRIM、LTRIM、FORMAT。對於簡單的函數咱們略過,下面咱們來說講幾個須要注意的地方。

LEN與DATALENGTH比較

咱們首先建立以下測試表

CREATE TABLE StringFun
(
    firststr VARCHAR(max) NOT NULL,
    secondstr TEXT NOT NULL
);

咱們插入測試數據

INSERT dbo.StringFun
        ( firststr, secondstr )
VALUES  ( '我是JeffckyWang,我來自於博客園,專一於.NET技術', -- firststr - varchar(max)
          '我是JeffckyWang,我來自於博客園,專一於.NET技術'  -- secondstr - text
          )

咱們首先利用LEN函數來返回firststr和secondstr的字符串長度大小

SELECT LEN(firststr) AS VARCAHRFieldSize 
FROM dbo.StringFun

SELECT LEN(secondstr) AS TEXTFieldSize 
FROM dbo.StringFun

好極了,出錯了。LEN函數沒法對TEXT進行操做。咱們接着往下看。

SELECT DATALENGTH(firststr) AS VARCAHRFieldSize 
FROM dbo.StringFun

SELECT DATALENGTH(secondstr) AS TEXTFieldSize 
FROM dbo.StringFun

此時未報錯誤,結果顯示爲47個字節大小。 既然LEN對文本無效,咱們不對文本操做就是。

SELECT LEN(firststr) AS VARCAHRFieldSize 
FROM dbo.StringFun

SELECT DATALENGTH(secondstr) AS TEXTFieldSize 
FROM dbo.StringFun

此時類型爲VARCAHR的firststr字節大小卻爲31,爲什麼,看到這裏咱們想必恍然大悟,在上述咱們講到常規字符會對中文以一個字符兩個字節大小存儲,可是這裏實際上返回的是實際字符大小,固然一個是存儲,一個是檢索,仍是有點不一樣,同時咱們也不會將中文存儲到VARCHAR中。到這裏咱們能夠得出結論。

結論:DATALENGTH函數是針對於TEXT,而LEN是針對於VARCHAR,對TEXT無效會報錯。

到這裏咱們還有一個特殊值未進行處理,那就是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'

咱們上述獲得的結果是LEN of NULL is NULL,DATALENGTH就再也不演示了。

結論:LEN和DATALENGTH對於NULL計算的結果就是NULL。

咱們再來看看兩者差別的一個小地方:

SELECT LEN('JeffckyWang  ') AS 'LEN'
SELECT DATALENGTH('JeffckyWang   ') AS 'DATALENGTH'

結論:LEN會刪除尾隨空格,而DATALENGTH不會

CHARINDEX與PATINDEX比較

CHARINDEX和PATINDEX字符串函數都是查詢返回指定匹配字符串的開始位置。

咱們先查詢一個字符串,此字符串在表中存在,以下:

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函數查找到了,而PATINDEX沒有查詢到呢?此時就說說兩者的區別,兩者都有兩個參數,第二個參數都是要匹配的字符串,可是PATINDEX函數必須在須要匹配的字符串以前或者以後添加百分號即通配符,而CHARINDEX函數則不須要。以下便可:

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;

結論:PATINDEX匹配字符串必須在字符串前面或者後面或者先後添加通配符,而CHARINDEX無需添加。

總結

本節咱們主要講解了SQL中的數據類型以及幾個須要注意的地方,簡短的內容,深刻的理解,咱們下節再會。

相關文章
相關標籤/搜索