我知道RowVersion
列的值本身并没有用,除了每次更新行时它都会改变。但是,我想知道它们是否对相对(不等式)比较有用。
如果我有一个带有RowVersion
列的表,则以下任一情况为真:
- 同时发生的所有更新(相同的更新语句或相同的事务)在
RowVersion
列中是否具有相同的值? - 如果我更新“A”,然后更新“B”,更新“B”中涉及的行是否会比更新“A”中涉及的行具有更高的值?
谢谢。
我知道RowVersion
列的值本身并没有用,除了每次更新行时它都会改变。但是,我想知道它们是否对相对(不等式)比较有用。
如果我有一个带有RowVersion
列的表,则以下任一情况为真:
RowVersion
列中是否具有相同的值?谢谢。
每个数据库都有一个计数器,每次对包含数据库列的表执行插入或更新操作时,该计数器都会递增。rowversion
这个计数器就是数据库rowversion
。这跟踪数据库中的相对时间,而不是可以与时钟关联的实际时间。每次修改或插入带有列的行时,都会将递增的数据库值插入该列中。rowversion
rowversion
rowversion
http://msdn.microsoft.com/en-us/library/ms182776.aspx
rowversion
s 都应该是唯一的。我冒昧地说,如果在同一个表中允许重复,它们实际上将毫无用处。同样让人相信rowversion
s 不会被复制的是 MSDN 关于不将它们用作主键的立场,不是因为它会导致违规,而是因为它会导致外键问题。对于增量多少的问题,MSDN 指出,“[ rowversion
] 跟踪数据库中的相对时间”,这表明它不是流体整数增量,而是基于时间的。然而,这个“时间”没有透露什么时候准确,而是什么时候插入/修改了与其他行相关的行。
一些额外的信息。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
我花了很长时间试图解决这个问题 - 要求在特定序列号之后更新列。时间戳实际上只是一个序列号 - 当像 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();
得到我想要的 - 自上次检查以来所有条目都发生了变化。
是什么让您认为 Timestamp 数据类型是邪恶的?数据类型对于并发检查非常有用。Linq-To-SQL 正是出于这个目的使用这种数据类型。
您的问题的答案:
1) 否。每次更新行时都会更新此值。如果您将行更新五次,则每次更新都会增加 Timestamp 值。当然,您意识到“同时发生”的更新实际上不会。反过来,它们仍然一次只出现一个。
2) 是的。
请注意,timestamp
从 SQL Server 2008 起已弃用。rowversion
应改为使用。
从MSDN 上的这个页面:
时间戳语法已弃用。此功能将在 Microsoft SQL Server 的未来版本中删除。避免在新的开发工作中使用此功能,并计划修改当前使用此功能的应用程序。
Rowversion 确实打破了 SQL 的“理想主义”方法之一 - UPDATE 语句是一个单一的原子操作,并且就像所有 UPDATE(对一行中的所有列以及表中的所有行)都发生在“同时”。但是在这种情况下,使用 Rowversion,可以确定一行的更新时间与另一行略有不同。
请注意,不能保证更新行的顺序(通过单个更新语句) - 巧合的是,它可能遵循与表的聚集键相同的顺序,但我不会指望这是真的。
要回答您的部分问题:根据 MSDN,您最终可能会得到重复的值:
可以使用 SELECT INTO 语句生成重复的 rowversion 值,其中 rowversion 列位于 SELECT 列表中。我们不建议以这种方式使用 rowversion。
每个数据库都有一个计数器,该计数器在数据库中完成的每一次数据修改时都会递增。如果包含受影响(通过更新/插入)行的表包含时间戳/行版本列,则数据库的当前计数器值存储在更新/插入记录的该列中。