對於大多數SQL Server編程開發者來說,當計算字符串的長度時,腦海中閃現的第一個函數是:Len(string),這個“長度”,默認情況下,是指字符的數量,一個英語字符是一個長度,一個漢字是一個長度。大多數的字符串函數,例如charindex,substring,stuff等函數,其位置都是針對字符數量的,這使得Len函數深入人心,但是,一個Unicode字符,占用的字節數量是2Byte,而一個普通的ASCII字符占用的字節數量是1Byte,當需要計算字符串占用的字節數量時,要如何計算?對於各個類型所占用的字節數量,又該如何計算?帶着這個疑問,讓我們一睹DataLength函數的廬山真面目。
一,字符數量
Len(string) 函數返回的數值是字符的數量(number of characters),在統計字符數量時,不包含結尾空格,但是包含前導空格。
示例,Len 函數返回的是字符的數量,而不是字符的字節數量。
declare @str_v varchar(10) declare @str_nv nvarchar(10) declare @str_nv_cn nvarchar(10) set @str_v=' ab ' set @str_nv=N' ab ' set @str_nv_cn=N' 悅光陰' select len(@str_v) as len_v ,len(@str_nv) as len_nv , len(@str_nv_cn) as str_nv_cn
二,字節數量
對於varchar類型,大家都知道,這是單字節字符,一個字符占用一個字節,總共能夠表示的256個字符;而對於nvarchar類型,一個字符占用兩個字節,能夠表示世界上所有的字符集,一個unicode字符占用兩個字節,如果要計算字符串占用的字節數量(number of bytes),請使用DataLength()函數,該函數統計字節數量時,字符串的所有字符都會計算在內,包括前導空格和結尾空格。
示例,每個unicode字符占2B,ASCII 字符占1B。
declare @str_v varchar(10) declare @str_nv nvarchar(10) declare @str_nv_cn nvarchar(10) set @str_v=' ab ' set @str_nv=N' ab ' set @str_nv_cn=N' 悅光陰' select datalength(@str_v) as len_v ,datalength(@str_nv) as len_nv , datalength(@str_nv_cn) as str_nv_cn
三,依賴字符數量的函數
對於字符串函數:left,right,其長度值是指字符的數量;對於含有位置參數的字符串函數,charindex、stuff 和 substring,是以字符數量來計算起始位置和長度。
STUFF ( character_expression , start , length , replaceWith_expression ) SUBSTRING ( expression ,start , length ) RIGHT ( character_expression , length ) LEFT ( character_expression , length )
四,查看數據類型(Data Type)所占用的存儲空間
DataLength()函數能過返回任意數據類型的變量所占用的字節數量,在設計表的schema時,為column定義窄的數據類型,在存儲海量數據行時,該函數十分有用。
例如,對於datetime類型占用固定的8B,DateTime2數據類型存儲日期和時間,占用的存儲空間不固定。根據存儲的時間部分 fractional seconds precision來確定DateTime2的Storage Size,6 bytes for precisions less than 3; 7 bytes for precisions 3 and 4. All other precisions require 8 bytes.
declare @dt1 datetime declare @dt2 datetime2(2) declare @dt3 datetime2(4) set @dt1=getdate() set @dt2=getdate() set @dt3=SYSDATETIME() select DATALENGTH(@dt1),DATALENGTH(@dt2),DATALENGTH(@dt3),@dt1,@dt2,@dt3
如果對time的精度(Precision)要求不是很高,保留2位毫秒,使用datetime2(2),比其他類型節省存儲空間。
參考doc: