【问题标题】:SQL Server optimistic locking - Returning changed timestamp valueSQL Server 乐观锁定 - 返回更改的时间戳值
【发布时间】:2011-03-15 13:59:24
【问题描述】:

我有一个实现乐观锁定的更新存储过程。存储过程如下所示:

ALTER PROCEDURE [dbo].[usp_Test] 
    @Id AS char(2),
       @recordTimestamp as timestamp
       ...
BEGIN       
    UPDATE XY
           ..
          WHERE ((Id = @Id) AND (recordTimeStamp = @recordTimestamp))       

if @@rowcount = 0
begin
RAISERROR ('this row was changed by another user', 18, 1)
end

SELECT timeStamp from XY where Id = @Idend

有没有更简单的方法来返回新的时间戳?我真的很想避免使用SELECT 语句。

【问题讨论】:

    标签: sql tsql stored-procedures sql-server-2008-r2 ado


    【解决方案1】:

    假设您至少可以使用 SQL Server 2005 OUTPUT

    UPDATE XY
    SET Col = 'foo'
    OUTPUT inserted.recordTimeStamp
    WHERE ((Id = @Id) AND (recordTimeStamp = @recordTimestamp))    
    

    或者使用表变量更接近地反映原始查询行为的版本。

    DECLARE @Timestamp TABLE(stamp binary(8))
    
    UPDATE XY
    SET col='foo'
    OUTPUT inserted.recordTimeStamp INTO @Timestamp
    WHERE (Id = @Id) AND (recordTimeStamp = @recordTimestamp) 
    
    if @@rowcount = 0
    begin
    RAISERROR ('this row was changed by another user', 18, 1)
    end
    
    SELECT stamp 
    FROM @Timestamp
    

    【讨论】:

    • 一切正常。唯一的问题是,它跳过了最后一个 if 子句。 ->> if @@rowcount = 0 begin RAISERROR ('此行已被另一个用户更改', 18, 1) end
    • 如果时间戳不匹配,@@rowcount 仍将为零,因此仍会引发错误。如果输出一个空的结果集,那么您也知道它不匹配。你也可以OUTPUT INTO @tablevariable 然后在最后选择。
    • @Damien - 是的,它是空的。在这种情况下,它不会返回时间戳。我认为这是严重程度为 18 错误的 OP 所期望的结果
    • @Martin - 是的,在我评论说如果更新成功,他正在寻求这个价值之后,我意识到。我最初将其阅读为某种形式的“我如何找出阻止我更新的新值是什么”,但意识到这也没有任何意义(因为你想知道其他列值)
    • @Damien - 是的,没错。如果同时更改了记录,我想抛出一个错误。错误(异常)在数据管理器(C# 代码)中稍后出现。
    【解决方案2】:

    显然我是盲人。 @@DBTS(http://msdn.microsoft.com/en-us/library/ms187366(SQL.90).aspx) 命令是正确的方法。

       ...
    if @@rowcount = 0 
    begin 
    RAISERROR ('this row was changed by another user', 18, 1) 
    end  
    SELECT @@DBTS
    

    【讨论】:

    • 不,我不这么认为。这看起来像是一个全局变量,而不是文档中的连接范围。如果您有并发,它可以从完全不同的行返回值。 OUTPUT 子句是正确的方法。我会按照我的回答去做。如果由于某种原因您的代码无法处理,那么您需要 OUTPUT inserted.recordTimeStamp INTO @TableVariable 然后在最后进行选择。
    • 是的,你是对的。全局变量@@DBTS 返回当前数据库的最后使用时间戳值 (VARBINARY)。我冲错了方向。谢谢。
    猜你喜欢
    • 2011-08-18
    • 2014-07-26
    • 1970-01-01
    • 2010-09-12
    • 2015-12-02
    • 2015-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多