Ton*_*raj 3 sql-server-2008 transaction ddl
当我尝试关闭下面的 SS Management Studio 窗口时出现错误
我知道 DDL 语句是隐式 COMMIT,下面的警告消息是因为 BEGIN TRAN 从不 COMMIT 或 ROLLBACK。更改 DDL 语句中止并且从未循环通过 CATCH 块。无法理解为什么在错误发生后控制没有传递给 CATCH 块(这在任何其他 DML 语句中都会发生)你能解释一下为什么 CATCH 中的语句从未针对此 DDL 错误执行吗?
怎么没抓到?因为 TRY / CATCH 不能捕获所有类型的错误。但是您可以通过将其包装在 EXEC() 中来捕获非系统关键的内容,例如:
BEGIN TRY
EXEC('ALTER TABLE...');
END TRY
Run Code Online (Sandbox Code Playgroud)
ALTER 中的错误将失败到 EXEC,然后将返回到 TRY/CATCH 块,报告一个简单的、可捕获的错误。
有关更多详细信息,TRY...CATCH的 MSDN 页面指出:
当以下类型的错误发生在与 TRY…CATCH 构造相同的执行级别时,它们不会被 CATCH 块处理:
阻止批处理运行的编译错误,例如语法错误。
语句级重编译过程中出现的错误,例如编译后由于名称解析延迟导致的对象名称解析错误。
关于对象名称解析错误的第二个要点是导致 ALTER 语句失败并且无法被 CATCH 块处理的原因。
编辑:
关于您关于“DDL 语句是隐式提交”的声明:我不确定您的确切含义,但所有(几乎所有)查询本身都是事务。这意味着,单查询批有没有用明确的BEGIN TRAN/ COMMIT/ ROLLBACK。如果语句失败,它会自动回滚,如果成功则它会自动提交。你只使用BEGIN TRAN/ COMMIT/ROLLBACK如果你要有条件地回滚出于某种原因结构。使用该TRY...CATCH结构来正确处理错误仍然是一个好主意,但是通过显式事务处理,您一无所获(至少使用问题中发布的代码)。发布的代码与以下代码之间绝对没有区别:
BEGIN TRY
EXEC('ALTER TABLE...');
END TRY
BEGIN CATCH
SELECT 'I''m in Catch';
END CATCH;
Run Code Online (Sandbox Code Playgroud)