2011-11-03 65 views
2

如果由于违反外键约束而无法成功执行删除语句,是否有办法在SQL Server中中止存储过程?默认情况下,该过程似乎忽略错误并继续下一个语句。在外键约束违规中取消存储过程

但是,对于其他类型的错误(例如,从不存在的表中删除),过程将中止。

示例步骤:

SET ANSI_NULLS ON 
SET QUOTED_IDENTIFIER ON 
GO 
CREATE PROCEDURE [dbo].[TestSP] 
AS 
BEGIN 
    SET NOCOUNT ON; 

    print 'BEFORE'; 

    DELETE FROM ExistingWithConstraints; 
    print 'AFTER DELETE ExistingWithConstraints'; 

    DELETE FROM NonExisting; 
    print 'AFTER DELETE NonExisting'; 
END 

产生输出(请注意,上述的最后一个消息不打印):

BEFORE 
<snip constraint violation error message> 
AFTER DELETE ExistingWithConstraints  
<snip invalid object name error message> 

回答

3

使用事务和恰当的错误处理

CREATE PROCEDURE [dbo].[TestSP] 
AS 
SET XACT_ABORT, NOCOUNT ON 
DECLARE @starttrancount int 

BEGIN TRY 
    SELECT @starttrancount = @@TRANCOUNT 

    IF @starttrancount = 0 
     BEGIN TRANSACTION 

    DELETE FROM ExistingWithConstraints; 
    DELETE FROM NonExisting; 

    IF @starttrancount = 0 
     COMMIT TRANSACTION 
END TRY 
BEGIN CATCH 
    IF XACT_STATE() <> 0 AND @starttrancount = 0 
     ROLLBACK TRANSACTION 
    RAISERROR [rethrow caught error using @ErrorNumber, @ErrorMessage, etc] 
END CATCH 
GO 

这是基于我的答案在这里:Nested stored procedures containing TRY CATCH ROLLBACK pattern?

+0

如果'@@ TRANCOUNT> 0',您可以使用保存点来回滚由“TestSP”完成的err处理程序修改 - 这是我们在此使用的更通用的模式。 – wqw

+0

@wqw:我自己不使用保存点:数据库调用应该是原子的。我跟着我的链接,你会看到Remus使用这些模板的另一个模板。您还必须小心使用XACT_ABORT,这会导致交易失败 – gbn

-1

执行进行以允许你检查@@ ERROR标准可变为了问题。一个更现代的方式来做事,虽然它使用在try..catch块加在2005年的SQL:

http://msdn.microsoft.com/en-us/library/ms179296.aspx

+0

-1所有提及@@错误 – gbn

+0

@gbn:为什么不呢? - 我仍然看到大量的编程方式(当然不是我)! –

+0

我们开始教育他们的时代,不是吗。 – gbn