SQL Server RowVersion / Timestamp - 比较

时间:2010-12-17 13:20:38

标签: sql-server comparison timestamp inequality rowversion

我知道RowVersion列的值本身并不适用,除非每次更新行时都会更改。但是,我想知道它们是否对相对(不平等)比较有用。

如果我的表格中包含RowVersion列,则表示以下任一项为真:

  • 同时发生的所有更新(相同的更新语句或同一事务)是否在RowVersion列中具有相同的值?
  • 如果我更新“A”,然后更新“B”,更新“B”中涉及的行的值是否会高于更新“A”中涉及的行?

感谢。

8 个答案:

答案 0 :(得分:34)

<强> From MSDN

对于在数据库中包含rowversion列的表上执行的每个插入或更新操作,每个数据库都有一个递增的计数器。此计数器是数据库rowversion。这会跟踪数据库中的相对时间,而不是可以与时钟关联的实际时间。 每次 一行rowversion被修改或插入时,递增数据库{ {1}} 已插入rowversion列。

http://msdn.microsoft.com/en-us/library/ms182776.aspx

  • 据我所知,系统中并不会同时发生任何事情。这意味着所有rowversion都应该是唯一的。我冒昧地说,如果在同一个表格中允许重复,它们将毫无用处。同样对rowversion未被复制的信誉是MSDN对不使用它们作为主键的立场,不是因为它会导致违规,而是因为它会导致外键问题。
  • 根据MSDN,“rowversion数据类型只是一个递增的数字......”所以是的,后来更大。

对于增加多少的问题,MSDN声明,“[rowversion]跟踪数据库中的相对时间”,这表明它不是流量整数递增,而是时间为基础。但是,这个“时间”没有显示何时正好,而是当与其他行相关时插入/修改了一行。

答案 1 :(得分:13)

一些其他信息。 RowVersion很好地转换为bigint,因此在调试时可以显示更好的可读输出:

CREATE TABLE [dbo].[T1](
    [Id] [int] IDENTITY(1,1) NOT NULL,
    [Value] [nvarchar](50) NULL,
    [RowVer] [timestamp] NOT NULL
) 

insert into t1 ([value]) values ('a')
insert into t1 ([value]) values ('b')
insert into t1 ([value]) values ('c')
select Id, Value,CONVERT(bigint,rowver)as RowVer from t1
update t1 set [value] = 'x' where id = 3
select Id, Value,CONVERT(bigint,rowver)as RowVer from t1
update t1 set [value] = 'y' 
select Id, Value,CONVERT(bigint,rowver)as RowVer from t1

Id  Value   RowVer
1   a   2037
2   b   2038
3   c   2039

Id  Value   RowVer
1   a   2037
2   b   2038
3   x   2040

Id  Value   RowVer
1   y   2041
2   y   2042
3   y   2043

答案 2 :(得分:6)

我花了很多时间尝试用这个来解决问题 - 要求在特定序列号后更新列。时间戳实际上只是一个序列号 - 当像BitConverter.ToInt64这样的c#函数需要littleendian时,它也是bigendian。

我最终在表格上创建了​​一个数据库视图,我希望数据来自别名列'SequenceNo'

SELECT     ID, CONVERT(bigint, Timestamp) AS SequenceNo
FROM         dbo.[User]

c#代码首先看到视图(即UserV)与普通表相同

然后在我的linq中我可以加入视图和父表并与序列号进行比较

var users =  (from u in context.GetTable<User>()
                join uv in context.GetTable<UserV>() on u.ID equals uv.ID
                where mysequenceNo < uv.SequenceNo
                orderby uv.SequenceNo
                select u).ToList();

得到我想要的东西 - 自上次检查以来所有条目都有所改变。

答案 3 :(得分:5)

是什么让你认为Timestamp数据类型是邪恶的?数据类型对于并发检查非常有用。 Linq-To-SQL为此目的使用此数据类型。

您的问题的答案:

1)否。每次更新行时都会更新此值。如果要将行更新为五次,则每次更新都会增加Timestamp值。当然,您意识到“同时发生”的更新实际上并非如此。它们仍然只能一次出现一个。

2)是的。

答案 4 :(得分:5)

就像注释一样,timestamp在SQL Server 2008之后已被弃用。应该使用rowversion代替。

来自MSDN上的this page

  

不推荐使用时间戳语法。此功能将在a中删除   Microsoft SQL Server的未来版本。避免使用此功能   新的开发工作,并计划修改当前的应用程序   使用此功能。

答案 5 :(得分:3)

Rowversion确实破坏了SQL的“理想主义”方法之一 - UPDATE语句是单个原子操作,并且就像所有UPDATE(一行中的所有列以及表中的所有行)都发生一样“同时”。但在这种情况下,使用Rowversion,可以确定一行的更新时间与另一行略有不同。

请注意,不保证更新行的顺序(通过单个更新语句) - 巧合可能遵循与表的聚簇键相同的顺序,但我不会指望它是真的

答案 6 :(得分:2)

要回答部分问题:根据MSDN,您最终可能会出现重复值:

  

使用SELECT INTO可以生成重复的rowversion值   rowversion列在SELECT列表中的语句。我们的确是   不建议以这种方式使用rowversion。

来源:rowversion (Transact-SQL)

答案 7 :(得分:1)

每个数据库都有一个计数器,该计数器在数据库中完成的每个数据修改时逐个递增。如果包含受影响(通过更新/插入)行的表包含时间戳/ rowversion列,则数据库的当前计数器值将存储在更新/插入记录的该列中。