我尝试将包含二进制数据的SQL Server列解码为varchar
数据类型。
我已经在其他一些主题中看到了如何将其转换为二进制文件,但不幸的是,他们的解决方案并不适合我。
我有一个名为TABLE_TEST
的表名,其中有一列名为SomeData
,为varchar(400)
数据类型。
如果我点击编辑表格,我看到那里有一些数据,但如果我运行一个简单的查询:
SELECT SomeData
FROM TABLE_TEST
数据不会显示为二进制数据。
所以在其他地方读书,我继续尝试:
SELECT CONVERT(BINARY(16), SomeData, 1)
FROM TABLE_TEST
我也尝试过风格2,它显示:
Msg 8114,Level 16,State 5,Line 1
将数据类型varchar转换为varbinary时出错。
我知道这个数据完全没问题,因为当我在c#应用程序中读取它时,我只是这样做:
byte[] someDataBuffer = new byte[400];
MemoryStream someDataStream = new MemoryStream(someDataBuffer);
BinaryReader binaryReader = new BinaryReader(someDataStream);
Int32 data1 = binaryReader.ReadInt32();
Int16 data2 = binaryReader.ReadInt16();
Int16 data3 = binaryReader.ReadInt16();
有没有办法在SQL端获得相同的结果或查询? 我的意思是一个查询,它将varchar列转换为二进制,然后我可以在SQL中以相同的方式读取该数据结构。
EDIT1:
请注意,二进制列大小是400,所以基本上varchar(400)和我读取每个的方式是for循环50次。因为每个循环我都读取Int32然后读取Int16和Int16。这意味着总共8个字节* 50次= 400(列的大小)。
我虽然跑了这样的东西:
DECLARE @i int = 0;
WHILE @i < 50
BEGIN
-- Read Int32
-- Read Int16
-- Read Int16
SET @i = @i + 1;
END
但是我如何解码那里的每一部分数据呢?
EDIT2:
看起来@DavidDubois的答案是正确的方向。但我仍然不确定为什么当我尝试在SQL中读取数据时它不会起作用,这可能是一些编码问题。我添加了一张图片来展示它的样子,所以它提出了这个想法:
当我尝试选择此数据或复制此数据时,它不会复制任何内容。
这就是为什么它让我认为编码设置为特殊的东西。我如何检查这个?
该数据库和列的排序规则设置为:SQL_Latin1_General_CP1_CI_AS
答案 0 :(得分:1)
这可以帮到你:
DECLARE @TestString VARCHAR(100) = 'Test' ;
SELECT @TestString AS [Raw],
CONVERT(VARBINARY(100), @TestString) AS BinaryFromString,
CONVERT(VARCHAR(100), CONVERT(VARBINARY(100), @TestString)) AS StringFromBinary ;
答案 1 :(得分:0)
-- A varchar(400) value actually contains binary data
-- That data consists of 50 triplets.
-- Each triplet consists of a 32-bit integer, and two 16-bit integers
-- How does one pull out these values from the original data?
-- Note that data is stored in little-endian format, while SQL Server uses BIG-endian,
-- so we need to use REVERSE
-- Declare variables to hold the triplet values
-- @i32 holds a 32-bit integer (int), while @j16 and @k16 holds 16-bit integers (smallint)
declare @i32 int
declare @j16 smallint
declare @k16 smallint
-- @C will hold the varchar(400) data
-- @B will be used to hold that same data in a binary representation
declare @C varchar(400)
declare @B varbinary(400)
-- As a test, let's first build such a string
-- The binary value starts empty
set @B = 0x
-- Loop 50 times
declare @i int
set @i=1
while @i<=50
begin
-- I've arbitrarily chosen values to store
set @i32 = 1000000000-7777777 * @i
set @j16 = @i32 % 11111
set @k16 = @i32 % 9999
print 'I=' + cast ( @i32 as varchar(10))
+ ' J=' + cast ( @j16 as varchar(10))
+ ' K=' + cast ( @k16 as varchar(10))
-- Convert each of the three values to varbinary, and append them to the complete binary value
set @B = @B + cast ( Reverse ( cast ( @i32 as varbinary(4))) as varbinary(4))
+ cast ( Reverse ( cast ( @j16 as varbinary(2))) as varbinary(2))
+ cast ( Reverse ( cast ( @k16 as varbinary(2))) as varbinary(2))
set @i=@i+1
end
-- This is what it looks like in binary
select @B as [In Binary]
-- Convert that binary value to characters
set @C = cast ( @B as varchar(400))
-- Let's look at those characters. They won't make much sense
select @C as [As Characters]
-- Now let's take that example, and reverse the process
-- Convert the character value back to binary
set @B = cast ( @C as varbinary(400))
--set @B = 0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080C69706EB280100000000000000000080C69706A22601000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-- Loop 50 times
set @i=1
while @i<50
begin
-- Pull out the appropriate bytes for each value, and convert those values back to integers
set @i32 = cast( cast(Reverse(substring( @B, @i*8-7, 4 ))as varbinary(4)) as int )
set @j16 = cast( cast(Reverse(substring( @B, @i*8-3, 2 ))as varbinary(2)) as smallint )
set @k16 = cast( cast(Reverse(substring( @B, @i*8-1, 2 ))as varbinary(2)) as smallint )
-- Let's take a look
select @i as [Idx], @i32 as [I], @j16 as [J], @k16 as [K]
set @i=@i+1
end