众所周知,以分号结束每个语句是一个很好的做法。假设我们有一些使用 RAISERROR
重新抛出异常的旧代码,并且我们希望将其与 THROW
交换。
来自:THROW
:
The statement before the THROW statement must be followed by the semicolon (;) statement terminator.
仅使用ROLLBACK
:
BEGIN TRY
-- some code
SELECT 1;
END TRY
BEGIN CATCH
-- some code
ROLLBACK
THROW;
END CATCH
我们得到“THROW”附近的语法不正确。
这是完全有效的。
但是使用ROLLBACK TRANSACTION
无需分号即可工作:
BEGIN TRY
-- some code
SELECT 1;
END TRY
BEGIN CATCH
-- some code
ROLLBACK TRANSACTION
THROW;
END CATCH
最后使用ROLLBACK TRANSACTION @variable
:
DECLARE @TransactionName NVARCHAR(32) = 'MyTransactionName';
BEGIN TRY
-- some code
SELECT 1;
END TRY
BEGIN CATCH
-- some code
ROLLBACK TRANSACTION @TransactionName
THROW;
END CATCH
我们再次得到“THROW”附近的语法不正确。
。
第二个示例起作用有什么特殊原因吗(向后兼容性/...)?
<小时/>编辑:
Erland Sommarskog 写了一篇很棒的文章: Using ;THROW
最佳答案
如果您更改代码,它实际上会引发错误。
BEGIN TRY
-- some code
SELECT 1/0;
END TRY
BEGIN CATCH
-- some code
ROLLBACK TRANSACTION
THROW;
END CATCH
你看
Msg 3903, Level 16, State 1, Line 7 The ROLLBACK TRANSACTION request has no corresponding BEGIN TRANSACTION.
它正在尝试回滚到名为 THROW
的保存点。
这是有效的语法,但在上面的示例中运行时失败,因为不存在事务。如果您处于开放交易中但没有这样的保存点(如下)
BEGIN TRY
BEGIN TRAN
SELECT 1/0;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
THROW;
END CATCH
ROLLBACK
您会看到以下内容。
Cannot roll back THROW. No transaction or savepoint of that name was found.
这种歧义大概就是为什么需要在 throw
之前添加分号的原因。
关于SQL Server - THROW 之前的分号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40596687/