更新 SQL Server 2012 中的 varbinary(MAX) 字段丢失最后 4 位
Update varbinary(MAX) field in SQLServer 2012 Lost Last 4 bits
最近想做一些数据修补,尝试更新一个varbinary(MAX)类型的列,更新值是这样的:
0xFFD8F...6DC0676
但是更新查询运行成功后,值变为:
0x0FFD8...6DC067
似乎最后 4 位丢失了,或者整个值右移了一个字节...
我尝试删除整行并 运行 一个 插入查询 ,同样的事情发生了!
谁能告诉我为什么会这样,我该如何解决?谢谢!
我尝试了几种不同长度的二进制文件,最大
43658个字符(每个代表4位,共约21KB),更新查询正常运行s。再多1个字符就会出现上面的"bug"...
PS1: 对于更短长度的varbinary作为更新值,一切都ok
PS2:如果有帮助,我可以post整个二进制字符串,但它真的很长,我不确定它是否适合post这里
已编辑:
感谢您的帮助!
有人建议,插入的值可能是4位的奇数个,所以在它前面追加了一个0。这是我的价值更新信息:
值是 43677 个字符长,不包括“0x”,这意味着 是的,它是奇数
它确实解释了为什么前面插入了一个“0”,但是没有解释为什么最后一个字符消失了...
那我做个实验:
我插入了一个偶数长度值,我在原值前手动添加了一个'0',
现在要更新的值为
0x0FFD8F...6DC0676
长度为 43678 个字符,不包括“0x”
结果没有运气,更新后的值还是
0x0FFD8...6DC067
您用于更新的二进制常量 0xFFD8F...6DC0676
似乎包含奇数个十六进制数字。并且 SqlServer 在模式的开头添加了半字节,以便它代表完整的字节数。
可以看到同样的效果运行下面的简单查询:
select 0x1, 0x104
这将 return 0x01
和 0x0104
。
截断可能是由于 SSMS 中的一些限制,可以在以下实验中观察到:
declare @b varbinary(max)
set @b = 0x123456789ABCDEF0
set @b = convert(varbinary(max), replicate(@b, 65536/datalength(@b)))
select datalength(@b) DataLength, @b Data
结果 returned 是 65536
和 0x123456789ABCDEF0...EF0123456789ABCD
,但是如果在 SSMS 中复制数据列,我将得到 43677 个字符长度的模式(这是没有前导 0x) ,实际上是 21838.5 字节。因此,您似乎不应该(如果这样做)依赖通过 SSMS 中的 copy/paste 获得的长二进制数据值。
可靠的替代方法可以使用中间变量:
declare @data varbinary(max)
select @data = DataXXX from Table_XXX where ID = XXX
update Table_YYY set DataYYY = @data where ID = YYY
最近想做一些数据修补,尝试更新一个varbinary(MAX)类型的列,更新值是这样的:
0xFFD8F...6DC0676
但是更新查询运行成功后,值变为:
0x0FFD8...6DC067
似乎最后 4 位丢失了,或者整个值右移了一个字节...
我尝试删除整行并 运行 一个 插入查询 ,同样的事情发生了!
谁能告诉我为什么会这样,我该如何解决?谢谢!
我尝试了几种不同长度的二进制文件,最大 43658个字符(每个代表4位,共约21KB),更新查询正常运行s。再多1个字符就会出现上面的"bug"...
PS1: 对于更短长度的varbinary作为更新值,一切都ok
PS2:如果有帮助,我可以post整个二进制字符串,但它真的很长,我不确定它是否适合post这里
已编辑: 感谢您的帮助!
有人建议,插入的值可能是4位的奇数个,所以在它前面追加了一个0。这是我的价值更新信息:
值是 43677 个字符长,不包括“0x”,这意味着 是的,它是奇数
它确实解释了为什么前面插入了一个“0”,但是没有解释为什么最后一个字符消失了...
那我做个实验:
我插入了一个偶数长度值,我在原值前手动添加了一个'0',
现在要更新的值为
0x0FFD8F...6DC0676
长度为 43678 个字符,不包括“0x”
结果没有运气,更新后的值还是
0x0FFD8...6DC067
您用于更新的二进制常量 0xFFD8F...6DC0676
似乎包含奇数个十六进制数字。并且 SqlServer 在模式的开头添加了半字节,以便它代表完整的字节数。
可以看到同样的效果运行下面的简单查询:
select 0x1, 0x104
这将 return 0x01
和 0x0104
。
截断可能是由于 SSMS 中的一些限制,可以在以下实验中观察到:
declare @b varbinary(max)
set @b = 0x123456789ABCDEF0
set @b = convert(varbinary(max), replicate(@b, 65536/datalength(@b)))
select datalength(@b) DataLength, @b Data
结果 returned 是 65536
和 0x123456789ABCDEF0...EF0123456789ABCD
,但是如果在 SSMS 中复制数据列,我将得到 43677 个字符长度的模式(这是没有前导 0x) ,实际上是 21838.5 字节。因此,您似乎不应该(如果这样做)依赖通过 SSMS 中的 copy/paste 获得的长二进制数据值。
可靠的替代方法可以使用中间变量:
declare @data varbinary(max)
select @data = DataXXX from Table_XXX where ID = XXX
update Table_YYY set DataYYY = @data where ID = YYY