【发布时间】:2011-06-29 22:16:28
【问题描述】:
使用 SQL Server 2008+。
我有一个 rowversion 列(又名时间戳),我从数据库中检索并使用以下代码将其转换为数字(20,0):
CONVERT(NUMERIC(20,0), RowVersionColumn + 0) AS [RowVersion]
稍后,我需要获取该数值(作为 ulong/UInt64 存储在 ADO.NET 数据集中),并将其转换回 rowversion 数据类型。
不过,这会产生问题。似乎虽然您可以转换为 numeric(20,0),但反向操作无法产生正确的值。例如:
DECLARE @MyNumericValue NUMERIC(20,0)
DECLARE @MyRowVersionValue ROWVERSION
SET @MyNumericValue = 12345
SET @MyRowVersionValue = CONVERT(rowversion, @MyNumericValue)
PRINT CONVERT(NUMERIC(20,0), @MyRowVersionValue + 0)
运行此代码会打印出 959447040 的值,而不是 12345。从 CONVERT 语句中删除“+ 0”会产生正确的结果,但我仍然无法可靠地获取曾经是 rowversion 的数值,并且将其转回一个行版本,其值应为应有的值。
下面是这个问题的一个更好的演示:
DECLARE @MyNumericValue NUMERIC(20,0)
DECLARE @MyRowVersionValue ROWVERSION
DECLARE @MyRowVersionValue2 ROWVERSION
SET @MyRowVersionValue = @@DBTS
SET @MyNumericValue = CONVERT(NUMERIC(20,0), @MyRowVersionValue + 0)
SET @MyRowVersionValue2 = CONVERT(rowversion, @MyNumericValue)
SELECT @MyRowVersionValue
SELECT @MyNumericValue
SELECT @MyRowVersionValue2
您的结果会因您的输入而异,但作为示例,我的输出是:
0x0000000003ADBB2F
61717295
0x140000012FBBAD03
第一个和最后一个值应该匹配,但它们不匹配。我猜这与二进制数据转换通常会导致填充这一事实有关,而这种填充会改变值。见:
http://msdn.microsoft.com/en-us/library/aa223991(v=SQL.80).aspx
想法?
编辑:澄清一下,我正在处理 rowversion/timestamp 的事实是偶然的。 BINARY(8) 而不是 ROWVERSION 也会出现同样的问题,因为它们是等效的数据类型。
【问题讨论】:
-
不确定应该归功于谁。没有人真正提供解决方案(显然他们也不能),因为这是一个 SQL Server 错误。参见:support.microsoft.com/kb/141664 最后,我只取二进制值并使用以下 C# 代码将其转换为 ulong:BitConverter.ToUInt64(rowVersionByteArray.Reverse().ToArray(), 0);.
标签: sql sql-server tsql sql-server-2008