TRY .. CATCH 有时无法捕获主键违规

Nat*_*lia 1 sql-server t-sql azure-sql-database azure

我编写了代码将记录更新到数据库。数据库是Azure DB,S4层。

更新和插入有时是高度并发的,因为它来自执行太多更新的应用程序。

该代码在大多数情况下都能成功运行,但有时会抛出 2627 异常(在 CATCH 语句内部处理)。到目前为止还无法弄清楚可能是什么问题。

我可以用 MERGE 语句替换它,但是我不太喜欢它,并且还想弄清楚这个 try and catch 发生了什么。

SET nocount ON;
IF NOT EXISTS(SELECT * FROM MyTable WHERE ID = @ID)
BEGIN TRY
INSERT INTO Table(ID, Value, TimeChanged) VALUES (@id, 'xxx', GETDATE())
END TRY
BEGIN CATCH
IF @@Error <> 2627 ----Violation of PRIMARY KEY constraint
THROW;
END CATCH

UPDATE MyTable SET Value = 'xxx' WHERE ID = @ID AND TimeChanged < GETDATE()

Run Code Online (Sandbox Code Playgroud)

Dav*_*oft 5

不确定这是否是问题所在,但您应该在 catch 块中使用ERROR_NUMBER()而不是 @@error 。

@@error 仅返回紧随导致错误的语句之后的语句中的错误号。while在catch语句中,ERROR_NUMBER()总是会给出抛出异常的错误。

无论如何,这样的东西应该可靠地工作,不会违反 PK:

SET nocount ON;
begin transaction
IF NOT EXISTS(SELECT * FROM MyTable with (updlock, holdlock) WHERE ID = @ID)
begin
  INSERT INTO Table(ID, Value, TimeChanged) VALUES (@id, 'xxx', GETDATE())
END 
else
begin
  UPDATE MyTable SET Value = 'xxx' WHERE ID = @ID AND TimeChanged < GETDATE()
end
commit transaction
Run Code Online (Sandbox Code Playgroud)