-2

我创建了这个非常基本的存储过程,当用户创建特定类型的项目时,我们的 cms 会调用它。但是,看起来有时我们会为使用相同数据创建的每个 cms 项目获得两行,但是是一个 off-by-one SourceID。我没有做太多的 SQL 工作,所以这可能是一些基本的事情 - 但我是否需要在存储过程中以某种方式显式锁定表以防止这种情况发生?

这是存储过程代码:

BEGIN
    SET @newid = (SELECT MAX(SourceID)+1 from [dbo].[sourcecode])

    IF NOT EXISTS(SELECT SourceId from [dbo].[sourcecode] where SourceId = @newid)
        INSERT INTO [dbo].[sourcecode]
            (
                SourceID,
                Description,
                RunCounts,
                ShowOnReport,
                SourceParentID,
                ApprovedSource,
                Created
            )
        VALUES
            (
                @newid,
                @Desc,
                1,
                @ShowOnReport,
                1,
                1,
                GetDate()
            )

    RETURN @newid
END

这是重复数据的示例(少了几个不相关的列):

SourceId    Description Created
676         some text   2012-10-17 09:42:36.553
677         some text   2012-10-17 09:43:01.380
4

4 回答 4

1

我确信这与SP无关。正如 Oded 所提到的,这可能是您的代码的结果。我在存储过程中看不到任何能够生成重复项的内容。另外,我不会使用 MAX(SourceId) + 1。如果你一直想要一个新的源 ID,为什么不使用“自动增量”呢?

于 2012-10-17T14:14:13.293 回答
0

使用存储过程时可以使用锁定。在我使用的那些我通常使用WITH (ROWLOCK). 锁定用于确保数据完整性。我认为一个简单的谷歌应该提供很多关于为什么你应该使用锁定的信息。

但正如其他评论员所说,看看你的代码中是否也没有任何东西。有没有两次调用相同方法的东西?是否存在引用正在更新的方法的“事件”?

于 2012-10-17T14:06:52.657 回答
0

正如评论中所说,我认为您的问题更多在于代码层;似乎没有任何数据违反任何限制。您可能希望在执行插入之前检查同一用户是否“最近”提交了相同的数据。

于 2012-10-17T14:12:56.540 回答
-2

描述可能是重复的,因为您通过单击两次按钮或其他方式调用了两次相同的函数。

您应该IDENTITY在 SourceID 列上使用 an 并使用该Scope_Identity()函数

如果您出于某种原因不想这样做,那么您应该将上述代码包装在隔离级别设置为的事务中Serializable

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRAN
    SET @newid = ....


COMMIT 
于 2012-10-17T14:06:54.547 回答