我在MSDN Lbrary中找到并且文章解释说try / catch不处理无法找到对象时抛出的错误。所以,即使我在try / catch中包装一个事务,回滚短语也不会执行:
BEGIN TRY
BEGIN TRANSACTION
SELECT 1 FROM dbo.TableDoesNotExists
PRINT ' Should not see this'
COMMIT TRANSACTION
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION
SELECT
ERROR_MESSAGE()
END CATCH
--PRINT 'Error Number before go: ' + CAST(@@Error AS VARCHAR)
go
PRINT 'Error Count After go: ' + CAST(@@Error AS VARCHAR)
PRINT 'Transaction Count ' + CAST(@@TRANCOUNT AS VARCHAR)
当对象不存在时,特别是涉及事务时,处理错误的推荐方法是什么?我应该用这一段代码来代替最后两个打印语句:
IF @@ERROR <> 0 AND @@TRANCOUNT > 0
BEGIN
PRINT 'Rolling back txn'
ROLLBACK TRANSACTION
END
go
PRINT 'Transaction Count again: ' + CAST(@@TRANCOUNT AS VARCHAR)
答案 0 :(得分:1)
您可以使用OBJECT_ID()来测试对象是否存在:
IF OBJECT_ID('MyTable') IS NULL RAISERROR('Could not find MyTable.', 18, 0)
答案 1 :(得分:0)
您为什么要尝试从不存在的表中检索数据?
数据库的基本构建块是一个表。不知道模式中的内容本质上是尝试将SQL用作动态语言,而不是。
我会重新考虑你的设计;如果不了解数据库中的表及其预期用途,其他人很难在这方面提供帮助。请在您的问题中添加更多信息。
修改强> 我已经阅读了BOL,并且当对象不存在时,建议的处理错误的方法如下:
您可以使用TRY ... CATCH来处理错误 在编译期间发生的 语句级重新编译 执行错误生成代码 TRY块中的单独批次。 例如,您可以通过放置来完成此操作 存储过程中的代码或 执行动态Transact-SQL 使用sp_executesql的语句。这个 允许TRY ... CATCH捕获错误 执行程度高于 错误发生。
我使用以下程序对此进行了测试
CREATE PROCEDURE [dbo].[BrokenProcedure]
AS
BEGIN
SET NOCOUNT ON;
SELECT * FROM MissingTable
END
GO
然后在TRY..CATCH
块中调用它:
BEGIN TRY
PRINT 'Error Number before: ' + CAST(@@Error AS VARCHAR)
EXECUTE [dbo].[BrokenProcedure]
PRINT ' Should not see this'
END TRY
BEGIN CATCH
PRINT 'Error Number in catch: ' + CAST(@@Error AS VARCHAR)
END CATCH
导致以下输出:
错误编号:0
catch中的错误号:208
这不是一个完美的解决方案,因为您必须为所有表访问创建过程(或使用动态SQL),但这是MS推荐的方法。
答案 2 :(得分:0)
现在,你已经遇到了一个有趣的问题(好吧,无论如何,对我来说)。您不应该启动事务,因为批处理将无法编译。但是,它可以编译,然后语句级别重新编译将失败。
See this question What is wrong with my Try Catch in T-SQL?
但是,在 情况下,您可以使用SET XACT_ABORT ON。这增加了可预测性,因为一种效果是自动回滚任何事务。它还会抑制错误266.请参阅此SO question
SET XACT_ABORT ON
BEGIN TRY
BEGIN TRANSACTION
SELECT 1 FROM dbo.TableDoesNotExists
PRINT ' Should not see this'
COMMIT TRANSACTION
END TRY
BEGIN CATCH
-- not needed, but looks weird without a rollback.
-- you could forget SET XACT_ABORT ON
-- Use XACT_STATE avoid double rollback errors
IF XACT_STATE() <> 0
ROLLBACK TRANSACTION
SELECT
ERROR_MESSAGE()
END CATCH
go
--note, this can't be guaranteed to give anything
PRINT 'Error Count After go: ' + CAST(@@Error AS VARCHAR)
PRINT 'Transaction Count ' + CAST(@@TRANCOUNT AS VARCHAR)