我之所以提出这个问题,是因为当子表中插入/更新/删除记录时,我希望记录的时间戳也随之变化。
时间戳可能不是最好的解决方案。如果不行,我该怎么办呢?我不想使用datetime,因为我认为那不是一种好的版本控制方式。我也不想使用整数,因为我不想读取值来递增它。
有什么建议吗?
UPDATE Table SET
IntColumn = IntColumn + 1
虽然技术上需要读取,但我认为这没有任何问题。
你可以直接更新为相同的值:
UPDATE Table SET
SomeColumn = SomeColumn
这将触发行版本更新。
补充:您可以创建一个视图,其中包含子项的最大行版本:
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、binary(8)和INSTEAD OF触发器实现自己的可更新版本...)
你能举个例子来说明你上次提到的那一点吗?听起来很有前途。
不,真的没有。;) 当你可以只更新到相同的值或使用视图时,这太麻烦了。这是两个最简单的选择。
但是,为了完整起见,一个默认为@@DBTS(返回数据库版本号)的binary(8)列,以及一个在UPDATE之后也将二进制列更新为新的@@DBTS的触发器,将为您提供一个伪-rowversion类型,您可以手动更新它。但与仅将其他列更新为其相同值相比,它不会更快或更好。
Ronnie,
首先,微软已经将 timestamp
语法停用,所以您需要使用 rowversion
。 其次,rowversion
总是与行相关联。
根据文档:
rowversion
每个数据库都有一个计数器,该计数器会为在数据库中包含 rowversion 列的表上执行的每个插入或更新操作递增。 此计数器是数据库的 rowversion。
但是,由于它在 SQL Server 中的实现方式,您需要使用触发器来实现您想要的功能。
类似于这样的代码:
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
信不信由你,这个更新操作会更新一个RowVersion/Timestamp列但是不设置列值。注意set
之后唯一的语句是@foo=@foo
。我正在使用Sql Server 2017。
declare @foo nvarchar(50);
update dbo.MyTable
set @foo = @foo
where Id = @id
你有考虑过使用触发器吗?这似乎更符合你的需求。
我曾经在一个应用程序上工作,其中时间戳遍布整个应用;但我们应该如何处理它们似乎有点难以捉摸,所以我们将其从模式中删除了。您可以将时间戳读入基于数据创建的对象中,并在更新时检查是否已更改,如果发现数据不正确,则回滚,但这需要大量样板代码而收益较少(至少在我工作的领域中是这样)。
在更好的想法出现之前,我要做的是在我的父表中添加一个名为 DateChildrenChanged 的 DateTime 列。
我将在子表上添加一个触发器,它将把 DateChildrenChanged 列设置为当前的 DateTime,当这种情况发生时,父表上的时间戳列也会被更新。
这样,我就可以使用时间戳列进行版本控制。
我仍然非常愿意听取意见。