在SQL Server中,使用數據類型 binary(n) 和 varbinary(n) 存儲字節流,或稱二進制數據,n是指字節數量:
- binary(n):固定長度為 n 字節,其中 n 值從 1 到 8,000 ,存儲空間為 n 字節;
- varbinary( n | max):可變長度,n 的取值范圍為 1 至 8,000,max 是指最大存儲空間是 2^31-1 個字節,即最大4GB;
- n:在表列定義或變量聲明語句中沒有指定 n,則默認長度為 1;在CAST 函數中沒有指定 n,則默認長度為 30;
在將數據轉換為二進制數據時,SQL Server會對生成的二進制數據進行填充或截斷,詳細的規則是:
- 填充(或擴展)的二進制數據是16進制的0x00的整數倍,這就是說,填充的字節中每一個bit都是0;
- 將字符類型轉換成二進制數據時,在數據的右側填充或截斷數據,填充數值是0x00;
- 將其他類型數據轉換成二進制數據時,在數據的左側填充或截斷數據,填充數值是0x00;在截斷數據時,保留低位的數據,將高位數值截斷;
一,二進制類型的特征
存儲單位是Byte,數據類型binary 和 varbinary 占用的存儲空間的單位不是bit,而是 byte
declare @varBi binary(1) set @varBi=1
輸出結果是:0x01,結果以16進制編碼顯示,共8bit。
為binary變量賦值,可以使用10進制數據為binary類型的變量賦值,也可以直接使用16進制數值為binary變量賦值;
declare @biA binary(1) set @biA= 0x01
字節流的逆序,可以使用reverse()函數對字節流進行逆序排列:
declare @bi varbinary(max)=123456 select @bi, cast(reverse(@bi) as varbinary(max)) --0x0001E240 0x40E20100
二,類型轉換
由於數據都是用字節存儲,二進制類型可以和所有其他類型的數據進行轉換。
1, 數值類型隱式轉換成binary類型
系統自動將 int類型隱式轉換成binary類型,但是,binary必須顯式強制轉換成int類型。
declare @varBi binary(1) set @varBi=1 select @varBi,cast(@varbi as int)
2, 字符類型不能隱式轉換成binary類型,需要顯式轉換
將字符類型轉換成binary類型的過程是:逐個將字符的ASCII碼轉換成二進制數據,末尾補0,或截斷末尾多余的字符
declare @varBi binary(8) set @varBi=cast('1h' as binary(8)) select @varBi,ascii('1'),ascii('h'),cast(@varbi as varchar),DATALENGTH(cast(@varbi as varchar))

輸出結果分析:
- 0x31 是16進制,換算成10進制數值是49,和字符“1”的ASCII值相同;
- 0x68 是16進制,換算成10進制數值是104,和字符“h”的ASCII值相同;
- 末尾補0:由於字符串的長度是2Byte,定長binary(8)的長度是8Byte,在binary(8) 類型的末尾補0,補齊8Byte;
- 在將binary轉換成字符類型時,輸出結果是字符 “1h”,而不是數字,說明,按照ASCII將數值轉換成字符;
- 轉換成字符串類型時,長度是8Byte,未顯示的字符是不可打印的;
三,將字符串翻譯(translate)成二進制類型
從字符數據類型翻譯成binary或varbinary類型時,將在右側發生截斷或填充,填充的是16進制的0x00。當從字符類型(char、varchar、nchar、nvarchar)轉換為不同長度的 binary 或 varbinary 數據類型時,SQL Server 將在二進制數據的右側填充或截斷數據。從字符串的左邊逐字節翻譯,如果字符串的長度大於binary的長度,則右邊截斷;如果字符串的長度小於binary的長度,則右邊填充0x00。
翻譯的字符必須是0-9、a-f,逐個把字符的ASCII碼翻譯成二進制數字,或者逐個把二進制數字對應ASCII碼,轉換為字符。默認情況下,對於二進制數據,0x是自動填充導結果的最左側。
1,轉換成binary或varbinary類型時,從數據的右側截斷數據
declare @varBi binary(2) set @varBi=cast('123' as binary(3)) select @varBi,cast(@varbi as varchar)

2,轉換成binary或varbinary類型時,從數據的右側填充數據,填充的數值是0x00
declare @varBi binary(8) set @varBi=cast('123' as binary(8)) select @varBi,cast(@varbi as varchar)

3,使用convert的風格0(style=0)把binary(或varbinary)翻譯成字符串
select convert(varchar(8), 0x4E616d65, 0),cast(0x4E616d65 as varchar(8))

4,使用convert的風格0(style=0)把字符串翻譯成binary(或varbinary)
select convert(varbinary(8), 'name', 0),cast('name' as varbinary(8))
四,使用convert進行字符串和binary(或varbinary)的轉換
如果要把二進制數據,按照顯示的字符轉換為字符串,那么就必須使用convert轉換,convert的第三個參數是style,共有兩種風格,分別是1 和 2,風格1要求0x必須在二進制數據的最左側,風格2要求0x不能出現在二進制數據的最左側。
1,使用convert把binary轉換為字符串
分別設置style是1和2,查看轉換的結果:當style為1時,字符串前面添加0x;當style為2時,字符串前面沒有0x;
declare @b binary(8) set @b=12 select convert(varchar(64),@b,1),convert(varchar(64),@b,2)

2,使用convert把字符串轉換為binary類型
如果字符串前面有0x字符,那么使用風格1(設置style=1);如果字符串前面沒有0x字符,那么使用風格2(設置style=2);
declare @c varchar(64),@d varchar(64) select @c='0x000000000000000C',@d='000000000000000C' select convert(binary(8),@c,1), convert(binary(8),@d,2)

五,將整數類型轉換為二進制類型
從整數類型轉換為 binary 或 varbinary 時,在數據的左側填充或截斷數據,填充將通過使用十六進制的零來完成。
1,從整數類型轉換為二進制類型時,在數據的左側截斷數據,即保留低位的數據,將高位數值截斷
declare @biToInt binary(1) set @biToInt=300 select @biToInt,cast(@biToInt as int)

分析:由於binary(1)是1Byte,最大值是255,發生上溢,左側發生截斷,舍棄左邊高位數值 256,保留低位數值44
2,從整數類型轉換為二進制類型時,在數據的左側填充數據,即在高位填充數值:0x00
declare @biToInt binary(3) set @biToInt= 12 select @biToInt,cast(@biToInt as int)

如果沒有發生溢出,那么不管int類型數值有多大,都能生成相同的值,如果binary長度較長,那么左側填充為0x00。
六,二進制數據的比較,將自動提升操作數的數據類型
在SQL Server中,字節大的二進制數據類型,其類型處於“高”位。在進行二進制數值比較之前,首先匹配兩個操作數的數據類型,將兩個操作數提升為相同的數據類型,這體現在比較兩個binary類型的變量時,將字節數低的數據類型提升,保持兩個操作數的字節數相同。提升的字節使用0x00填充,並且是在右側填充,這將增大binary的數值。
1,自動提升數據類型,在右側填充0x00
declare @biA binary(1) declare @biB binary(2) set @biA=1 set @biB=2 select @biA,@biB,iif(@biA >= @biB,'>=','<')

輸出結果分析:在比較時,SQL Server將變量@biA 的數據類型提升為binary(2),在右側填充1byte,變成0x0100,數值是256,所以比較的結果是 >=;
如果變量@biB的值是257,那么輸出的結果將是<,因為,@biA填充之后,是0x0100,比0x0101小;
declare @biA varbinary(1) declare @biB varbinary(2) set @biA=1 set @biB=257 select @biA,@biB,iif(@biA >= @biB,'>=','<')

參考文檔:
