2010-01-29 83 views
6

我有一个带有时间戳列的sql服务器表。有没有办法强制时间戳列更改没有实际的记录更新?如何更新SQL服务器时间戳列而不更改记录数据

我问的原因是因为我希望在子表中插入/更新/删除记录时更改记录的时间戳。

时间戳可能不是执行此操作的最佳方式。如果不是,我该怎么办?我不想使用日期时间,因为我觉得这不是一种好的版本控制方式。我不想使用整数,因为我不想读取值来递增它。

对此提出建议?

+0

日期时间通常用于上次更改columns..is此不同的东西,也可以解释,为什么你不希望使用的DateTime? – dan 2010-01-29 21:46:39

+1

我阅读了一篇关于为什么DateTime数据类型不应该用于版本控制和乐观并发的文章。我不记得每一个细节,但它在当时是有道理的。我相信这是因为数据类型的精确性,理论上更新可能发生在导致竞争条件的完全相同的实例上。 – 2010-01-29 22:00:50

+0

仅当数据库未提供日期/时间时 - SQL Server DATETIMEs仅需几分之一秒:http://msdn.microsoft.com/en-us/library/ms187819.aspx – 2010-01-29 23:08:12

回答

9

我不想使用整数,因为我不想读取值来递增它。

UPDATE Table SET 
    IntColumn = IntColumn + 1 

虽然,它在技术上需要读,我没有看到它的任何问题。

你总是可以只更新到相同的值:

UPDATE Table SET 
    SomeColumn = SomeColumn 

将触发rowversion更新为好。

此外:你可以做一个视图与孩子的最大rowversion:

SELECT Parent.*, MaxChildRowVersion as ChildVersion 
FROM Parent 
JOIN (
    SELECT ParentId, MAX(RowVersion) as MaxChildRowVersion 
    FROM Child 
    GROUP BY ParentId 
) as Child ON 
    Parent.ParentId = Child.ParentId 

但是,不,你不能直接更新一个rowversion列(虽然你可以实现自己的更新与@@ DBTS,二进制(8)和INSTEAD OF触发器...)

你能举出最后一点的例子吗?听起来很有希望。

不,实际上没有。 ;)当您只需更新相同的值或使用视图时,它的工作量太大。这是最简单的两个选项。

但是,要完成一个默认为@@ DBTS(返回数据库版本号)的二进制(8)列和一个AFTER UPDATE触发器,该触发器也将二进制列更新为新的@@ DBTS给你一个psuedo-rowversion类型,然后你可以手动更新。它不会更快或更好,只是将其他列更新为相同的值。

+0

您能举出最后一点的例子吗?听起来很有希望。 – 2010-01-29 22:06:04

1

你看过使用triggers?这似乎更适合你以后的事情。

我工作过的应用程序曾经有过时间戳的问题;正是我们应该对他们做的事情证明是有点难以捉摸,所以我们审计了他们的模式。您可以根据数据读取您创建的对象的时间戳,并检查当您更新和回滚时它是否发生更改(如果您发现数据很脏),但是这样做会带来很多不利的样板(在至少在我工作的领域)。

+0

我其实。但我仍然需要在触发器中执行某些操作才能更新时间戳列。这是我的问题。 – 2010-01-29 21:53:02

0

我打算做的事情,直到一个更好的想法出现,是将一个DateTime列添加到我的父表称为DateChildrenChanged。

我将在将在DateChildrenChanged列设置为当前日期时间,这时,在父表中的时间戳列也将被更新子表中添加一个触发器。

这样我使用时间戳列的版本。

我还是要想法很开放。

+0

我认为这是最好的选择。保持您的TIMESTAMP/ROWVERSION版本化实际行。如果你需要版本你的子行 - 在那里有一个TIMESTAMP/ROWVERSION列 – 2010-01-30 09:47:30

4

罗尼,

所有timestamp语法首先是由微软弃用,因此,你需要使用rowversion,第二的rowversion始终是关系到该行。

从文档:

rowversion

每个数据库具有包含内的一个rowversion柱时递增对于被桌子上的执行的每个插入或更新操作的计数器数据库。这个计数器是数据库rowversion

但是,因为它在SQL服务器中实现的方式,您需要使用触发器来实现您想要的。

事情是这样的:

CREATE TRIGGER tgUpdateParentRowVersion ON ChildTable FOR INSERT, DELETE, UPDATE 
AS 
BEGIN 
    /* 
    * The updates below force the update of the parent table rowversion 
    */ 
    UPDATE ParentTable 
     SET ChildUpdate = ChildUpdate + 1 
    FROM ParentTable a 
    JOIN inserted i on a.pkParentTable = i.fkParentTable 

    UPDATE ParentTable 
     SET ChildUpdate = ChildUpdate - 1 
    FROM ParentTable a 
    JOIN deleted  d on a.pkParentTable = d.fkParentTable 
END 
+0

关于弃用,我反过来说:rowversion已被弃用。我可能是错的... – 2010-01-29 22:01:57

+0

@罗尼:你**是错的,保罗是对的。因为它的名字引起了很多混淆(人们认为有一种将日期和时间转换回来的方法),TIMESTAMP已被弃用。 ROWVERSION是新的方式去 – 2010-01-30 09:46:49

+0

我站在纠正。谢谢。 – 2010-01-31 06:18:15