Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/76.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql 当对象不存在时处理事务错误_Sql_Transactions_Try Catch - Fatal编程技术网

Sql 当对象不存在时处理事务错误

Sql 当对象不存在时处理事务错误,sql,transactions,try-catch,Sql,Transactions,Try Catch,我在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 TRANSACT

我在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)

为什么要尝试从不存在的表中检索数据

数据库的基本构造块是表。不知道模式中有什么实质上是试图将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块中调用它:

产生以下输出:

之前的错误编号:0

捕获错误号:208


这不是一个完美的解决方案,因为您必须为所有表访问创建过程或使用动态SQL,但这是MS.推荐的方法。

现在,您遇到了一个有趣的问题,不管怎样,对我来说。您不应该启动事务,因为批处理无法编译。但是,它可以编译,然后语句级重新编译失败

但是,在这两种情况下,您都可以使用。这增加了可预测性,因为其中一个效果是自动回滚任何事务。它还抑制了错误266。你也看到了吗


您可以测试对象ID为的对象是否存在:

IF OBJECT_ID('MyTable') IS NULL RAISERROR('Could not find MyTable.', 18, 0)

有时在动态环境中,您不知道精确的模式;另一个进程可能正在更改数据库结构,因此正常的try/catch异常处理应该正常工作。是的,try/catch处理应该正常工作,但我没有为MS辩护;我只是不同意使用数据库。Tony,这种情况出现在我们的测试和开发环境中,我们有多个开发人员同时处理他们正在进行的更改。这是我无法控制的情况,所以我无法改变。然而,由于测试中的对象可能会发生更改,所以我需要能够处理由丢失的对象生成的错误,我认为try/catch机制应该能够处理这些错误。既然没有,我正在试图找出使用事务的最佳方式,以便我负责的更改不会以某种不一致的状态结束。@gr928x:我已更新了答案,以包括处理此错误的方法。但是,如果有多个开发人员修改代码所依赖的DB对象,那么您的更改控制过程就会中断。如果您无法更改流程,请尝试获取数据库的个人副本以开发代码,并完全避免问题。是的,我可以,但这是不可扩展的。想象一下,如果我正在推出一个涉及50个对象的测试脚本,我会对每个对象进行测试吗?在我看来,try/catch应该首先处理错误。
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)
IF OBJECT_ID('MyTable') IS NULL RAISERROR('Could not find MyTable.', 18, 0)