循环可以自行锁定吗?
昨晚,测试团队打开了一个奇怪的嘀嗒声。 该应用程序有一个网格,用户可以检查要推迟的事件 测试人员选择了两个事件(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等),我也测试了隐式转换问题。
这个问题只发生过一次,即使使用备份也无法复制,但如果我找不到原因,我担心它会在生产中再次发生。
答案 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