【问题标题】:SQL Server varbinary bigint with BitConverter.ToInt64 values are differentSQL Server varbinary bigint 与 BitConverter.ToInt64 值不同
【发布时间】:2012-01-18 00:27:55
【问题描述】:

我将我的long 值保存在 SQL Server 表中为varbinary(max)

var savedValue = BitConverter.GetBytes(longValue);

现在我需要在 T-SQL 查询中使用该值,但是当我尝试获取值时:

select cast(Value as bigint) from dbo.MyValues

它返回不同的数值。例如,如果我在 .NET 中保存了 -8588797048854775808,在 T-SQL 中我会得到 33802181122903688

请告诉我有什么问题?这个问题有解决办法吗?

【问题讨论】:

  • 为什么首先将 64 位整数保存为 varbinary?
  • 通常,您会将 C# 中的 long 存储为 SQL Server 中的 bigint。您尝试将long 存储为varbinary 是否有特殊原因?
  • 因为 DB 字段不只包含 int64 类型的值。
  • 您可以创建一个 C# 程序集并使用 SQL-CLR 将其安装到 SQL Server 中,以再次处理此转换回Int64....
  • 您的问题是绝对正确的,但在我的情况下,我只是重构已经存在的解决方案。我想按类型将该列划分为新的其他列。而且我需要将数据从旧列传输到新列而不会丢失,实际上我不能使用 .NET 应用程序或 CLR Intergating 来实现我的目标。

标签: sql-server tsql bigint


【解决方案1】:

varbinary 转换到bigint(和返回)使用网络字节顺序(大端)。 BitConverter 使用运行它的机器的字节序(x86 和 x64 为小字节序)。

因此,BitConverter.GetBytes 在 -8588797048854775808 (0x88CE7696E7167800) 上运行是 {0x00,0x88,0xE9,0x18,0x69,0x89,0x31,0x77},cast 在 {0x09,0x88,0x18,x0xE, ,0x31,0x77} 是 0x0088E91869893177 = 38536887891734903。

最明显的做法是首先将 64 位整数存储为 64 位整数。

如果您确实需要进行此转换,那么:

var savedValue = BitConverter.GetBytes(IPAddress.HostToNetworkOrder(longValue))

将交换字节,同时也是可移植的,如果在大端机器上运行它不会交换字节。

或者,如果您出于某种原因不想使用 System.Net 命名空间,或者如果您想扩展到三个 IPAddress.HostToNetworkOrder 手柄以外的类型,请使用:

var savedValue = BitConverter.GetBytes(longValue);
if(BitConverter.IsLittleEndian)
  Array.Reverse(savedValue);

【讨论】:

  • 感谢您对此问题的解释。但我不打算再次将“长”值保存到“varbinary”。我只需要一些工具来获取该列中已经存在的“bigint”值,就像我在“.NET BitConverter.ToInt64”中获取值一样。我需要类似'Array.Reverse(savedValue);'仅在“TSQL”查询环境中
  • 谢谢乔恩我找到了!在那种情况下,我需要在TSQL 中使用reverse 函数:select cast(cast(reverse(Value) as varbinary(max)) as bigint) from dbo.MyValues
  • 不管提问者的数据库设计如何,这个问题帮助我在尝试实现与 T-SQL HASHBYTES 函数等效的 C# 时解决了类似的问题。我什至没有意识到字节序不同的可能性。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-17
  • 2015-06-13
  • 1970-01-01
  • 1970-01-01
  • 2020-11-27
  • 1970-01-01
相关资源
最近更新 更多