循环可以锁定吗?

时间:2014-08-27 19:49:08

标签: sql sql-server tsql

循环可以自行锁定吗?

昨晚,测试团队打开了一个奇怪的嘀嗒声。 该应用程序有一个网格,用户可以检查要推迟的事件 测试人员选择了两个事件(ID:1和5),推迟了两个但没有更新状态

我知道必须更新[Incident]表并在[IncidentDetail]表中插入一条新记录 我向他们询问并喜欢这个:

Id IncidentKindCode TransportEntryId CreateDate             IncidentStatus CloseDate
-- ---------------- ---------------- ---------------------- -------------- ---------
1  11301            52               2014-08-26 19:23:21.47 1              NULL
5  11301            56               2014-08-26 20:06:17.94 0              NULL

Id IncidentId  InsertDate             DetailKind Reason    IncidentUser PostponeDate
-- ----------- ---------------------- ---------- --------- ------------ -----------------------
9  1           2014-08-26 20:28:37.37 1          TEST TEST 8            2014-08-27 00:00:00.000
10 5           2014-08-26 20:28:37.37 1          TEST TEST 8            2014-08-27 00:00:00.000

测试者抱怨是有效的,因为[Incident]。[IncidentStatus]值此时必须为零。 在挖掘之后,我捕获了应用程序发送到服务器的确切查询(感谢分析器)。

declare @p1 int
set @p1=2
exec sp_prepexec @p1 output,N'@IDINCIDENT varchar(max) ,@REASON varchar(max) ,@USERCODE varchar(max) ,@POSTPONEDATE varchar(max) ',N'
DECLARE @ARRAY VARCHAR(8000), @DELIMITADOR VARCHAR(100), @SELECTEDID VARCHAR(8000);

SELECT @ARRAY = @IDINCIDENT
SELECT @DELIMITADOR = '';''

IF LEN(@ARRAY) > 0 SET @ARRAY = @ARRAY + @DELIMITADOR

WHILE LEN(@ARRAY) > 0
BEGIN

    SELECT @SELECTEDID = LTRIM(SUBSTRING(@ARRAY, 1,
    CHARINDEX(@DELIMITADOR, @ARRAY) - 1))

    BEGIN
        UPDATE [dbo].Incident SET INCIDENTSTATUS = 1 WHERE ID = @SELECTEDID
        INSERT [dbo].IncidentDetail (INCIDENTID, DETAILKIND, REASON, INCIDENTUSER, POSTPONEDATE)
                       VALUES (@SELECTEDID, 1, @REASON, @USERCODE, @POSTPONEDATE);
    END

    SELECT @ARRAY = SUBSTRING(@ARRAY,
    CHARINDEX(@DELIMITADOR, @ARRAY) + 1, LEN(@ARRAY))
END
',@IDINCIDENT='1;5',@REASON='querty',@USERCODE='1',@POSTPONEDATE='2014-08-28 00:00:00'
select @p1

没有触发器,没有其他更新没有待处理的事务。 据我所知,即使第一次循环迭代阻止第二次迭代到更新失败的点,也必须引发异常并回滚所有事务。

在插件工作时,更新可能会失败,这似乎是错误的。 所有列都有标准类型(Int,Varchar(100),DateTime等),我也测试了隐式转换问题。

这个问题只发生过一次,即使使用备份也无法复制,但如果我找不到原因,我担心它会在生产中再次发生。

1 个答案:

答案 0 :(得分:3)

我不明白你真正想做什么。我根据自己的理解给你一个方法。您可以检查该条目是否得到更新,如果更新,则在IncidentDetail中插入。

UPDATE [dbo].Incident SET INCIDENTSTATUS = 1 WHERE ID = @SELECTEDID

If Exists(  Select  1
            From    [dbo].Incident As I
            Where   I.ID = @SELECTEDID
                    And I.INCIDENTSTATUS = 1
         )
Begin
    INSERT [dbo].IncidentDetail (INCIDENTID, DETAILKIND, REASON, INCIDENTUSER, POSTPONEDATE)
                       VALUES (@SELECTEDID, 1, @REASON, @USERCODE, @POSTPONEDATE);
End