SQL Server - THROW 之前的分号

标签 sql sql-server tsql sql-server-2012

众所周知,以分号结束每个语句是一个很好的做法。假设我们有一些使用 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

LiveDemo

最后使用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/

相关文章:

sql - 使用 T-SQL 附加多个数据库

sql - Rails - 不明确的列名 : id

sql - 如何在 SQL Server 中将空字符串 (' ' ) 插入小数或数字?

SQL 查询查找每月周年纪念日的用户

sql - 每十步选择SQL

java - 防止表单生成的 SQL 注入(inject) SQL - NO PreparedStmts

mysql 选择计数不同行数量

sql - 2012 SQL作业问题

sql-server-2008 - SQL Server 顶部,顶部和底部都有关系

sql - 如何在 T-SQL 中的位字段上创建三元条件