最近,我想做一些数据修补,并尝试更新 varbinary(MAX) 类型的列,更新值是这样的:
0xFFD8F … 6DC0676
但是,更新查询成功运行后,该值将变为:
0x 0 FFD8 … 6DC067
似乎最后4位丢失了,或者整个值右移了一个字节…
我试图删除整行并运行一个 插入查询 ,发生同样的事情!
谁能告诉我为什么会这样?如何解决?谢谢!
我尝试了几种不同长度的二进制文件,最大为 43658个 字符(每个字符代表4位,总计约21 KB),更新查询正常运行。再增加1个字符将使上述“错误”出现…
PS1 :对于较短长度的varbinary作为更新值,一切正常
PS2 :如果有帮助,我可以将整个二进制字符串发布出来,但是它确实很长,我不确定是否适合在这里发布
编辑: 感谢您的帮助!
就像有人建议的那样,插入的值可能是4位的奇数,因此在其前面有一个0附加值。这是我关于值的更新信息:
该值是 43677个 字符,长后缀 有 “ 0x”,这 是肯定的,很奇怪
它确实说明了为什么在前面插入了“ 0”,但 没有说明为什么最后一个字符消失了…
然后我做一个实验:
我插入一个 偶数长度值,并在原始值之前手动添加一个‘0’ ,
现在要更新的值是
0x 0 FFD8F … 6DC067 6
长度为 43678个 字符,不包括“ 0x”
结果是没有运气,更新后的值仍然
0x0FFD8 … 6DC067
0xFFD8F...6DC0676您用于更新的二进制常量似乎包含十六进制数字的奇数个。并且SqlServer在模式的开头添加了半字节,以便表示整个字节数。
0xFFD8F...6DC0676
您可以通过运行以下简单查询看到相同的效果:
select 0x1, 0x104
这将返回0x01和0x0104。
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
返回的结果是65536和0x123456789ABCDEF0...EF0123456789ABCD,但是,如果在SSMS中复制数据列,则得到的格式为43677个字符的长度(这不带前导0x),有效长度为21838.5字节。因此,似乎(如果愿意)您不应该依赖通过SSMS中的复制/粘贴获得的长二进制数据值。
65536
0x123456789ABCDEF0...EF0123456789ABCD
可靠的替代方法可以使用中间变量:
declare @data varbinary(max) select @data = DataXXX from Table_XXX where ID = XXX update Table_YYY set DataYYY = @data where ID = YYY