0

我在 SQL Server 2008R2 数据库中有 3 个表,我需要一个接一个地填写它们的记录,所以我使用事务来完成这项工作没有问题。基本上我在事务中间有 2 个 INSERT 存储过程查询,以在这些表中插入记录,如下面的代码;

事务在 ASP.NET 的 C# SqlTransaction 类中处理。以下程序只是在事务中间使用。

第一张表:

ALTER PROCEDURE [INSERT_RESOURCE]
  @docID int,
  @resTitle nvarchar(500),
  @resCategory nvarchar(100),
  @resType nvarchar(50),
  @resLink nvarchar(MAX),
  @createdBy nvarchar(50),
  @createdDateTime datetime
AS 
BEGIN 
  INSERT INTO Resource
   VALUES(@resTitle, @resCategory, @resType, 
          @resLink, @createdBy, @createdDateTime)
END

第二张表:

CREATE PROCEDURE [INSERT_RESOURCE_DOCUMENT]
  @docName nvarchar(200),
  @docSize nvarchar(50),
  @docType nvarchar(50),
  @docPath nvarchar(MAX),
  @docTitle nvarchar(100),
  @uploadBy nvarchar(50),
  @uploadDateTime datetime
AS
BEGIN
INSERT INTO Document
        VALUES(@docName, @docSize, @docType, @docPath, 
                           @docTitle, @uploadBy, @uploadDateTime)

INSERT INTO Resource_Document         --Third table
    VALUES(
           (SELECT TOP 1 ResourceID FROM Resource  ORDER BY ResourceID DESC), 
           (SELECT TOP 1 DocID FROM Document  ORDER BY DocID DESC)
          )

上述过程工作正常,但可能的问题可能出在第三个过程上,即使用前两个表的最后一个 ID 在第三个表中插入数据,但由于最后一个 INSERT 语句使用的是 SELECT TOP 1 查询如果同时其他人使用相同的事务将一些值添加到前两个表中,它可能会选择错误的 id 。所以我想知道如何解决此交易中的问题?

我可以在第三个存储过程中使用其他方法从前两个表中获取这些 id 吗?

4

2 回答 2

1

你的问题是范围。您希望在该事务期间获得该用户的最后插入值。您的 select top 1 查询打破了用户的范围,并可能为任何用户选择最后插入的值。

要保持在用户范围内,请利用 SQL 的范围方法。将所有这 3 个操作转换为一个存储过程,然后使用该SCOPE_IDENTITY()方法获取最后插入到此会话/用户的标识列中的值。这将安全地保证用户不会得到彼此的插入值。

在此处阅读更多信息:http: //msdn.microsoft.com/en-us/library/ms190315.aspx

于 2013-06-07T05:33:27.103 回答
0

当同时添加两条记录时,第三个脚本肯定会导致问题。

我认为您可以放置​​一个后触发器(对于Resource上的每个插入)和一个更新后触发器(对于Document上的每个插入)。或者您可以加入上述两个表(Resource & Document),然后创建一个触发器,将数据添加到第三个表(Resource_Document

供参考 - http://msdn.microsoft.com/en-us/library/ms189799.aspx

于 2013-06-07T05:58:57.133 回答