如何在sql server中重新抛出同样的exception

我想重新抛出在我的try块中发生的sql服务器中的相同的exception。 我能够抛出相同的消息,但我想抛出同样的错误。

BEGIN TRANSACTION BEGIN TRY INSERT INTO Tags.tblDomain (DomainName, SubDomainId, DomainCode, Description) VALUES(@DomainName, @SubDomainId, @DomainCode, @Description) COMMIT TRANSACTION END TRY BEGIN CATCH declare @severity int; declare @state int; select @severity=error_severity(), @state=error_state(); RAISERROR(@@Error,@ErrorSeverity,@state); ROLLBACK TRANSACTION END CATCH 

RAISERROR(@@Error, @ErrorSeverity, @state);

这行会显示错误,但我想要的function。 这引起错误号码50000错误,但我想erron号码被抛出,我通过@@error

我想在前端捕获这个错误

 catch (SqlException ex) { if ex.number==2627 MessageBox.show("Duplicate value cannot be inserted"); } 

我想要这个function。 这是使用raiseerror无法实现的。 我不想在后端给自定义错误消息。

RAISEERROR应该返回下面提到的错误,当我传递ErrorNo被抛出catch

 Msg 2627, Level 14, State 1, Procedure spOTest_DomainInsert, 

第14行违反UNIQUE KEY约束“UK_DomainCode”。 不能在对象'Tags.tblDomain'中插入重复的键。 该语句已终止。

编辑:

有什么可以是不使用try catch块的缺点,如果我想在前端处理exception考虑存储过程包含多个需要执行的查询

这是一个function齐全的干净代码示例,用于在发生错误时回滚一系列语句并报告错误消息。

 begin try begin transaction; ... commit transaction; end try begin catch declare @ErrorMessage nvarchar(max), @ErrorSeverity int, @ErrorState int; select @ErrorMessage = ERROR_MESSAGE() + ' Line ' + cast(ERROR_LINE() as nvarchar(5)), @ErrorSeverity = ERROR_SEVERITY(), @ErrorState = ERROR_STATE(); rollback transaction; raiserror (@ErrorMessage, @ErrorSeverity, @ErrorState); end catch 

SQL 2012引入了throw语句:

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

如果没有参数指定THROW语句,它必须出现在CATCH块内。 这会导致捕获的exception被提出。

 BEGIN TRY BEGIN TRANSACTION ... COMMIT TRANSACTION END TRY BEGIN CATCH ROLLBACK TRANSACTION; THROW END CATCH 

我认为你的select是:

  • 不要误会(让它冒泡)
  • 举一个自定义的

在某些时候,SQL可能会引入一个重新命令,或者只能捕获某些错误。 但现在,使用一种解决方法。 抱歉。

回溯到CATCH块(pre-SQL2012代码,在SQL2012及更高版本中使用THROW语句):

 DECLARE @ErrorMessage nvarchar(4000) = ERROR_MESSAGE(), @ErrorNumber int = ERROR_NUMBER(), @ErrorSeverity int = ERROR_SEVERITY(), @ErrorState int = ERROR_STATE(), @ErrorLine int = ERROR_LINE(), @ErrorProcedure nvarchar(200) = ISNULL(ERROR_PROCEDURE(), '-'); SELECT @ErrorMessage = N'Error %d, Level %d, State %d, Procedure %s, Line %d, ' + 'Message: ' + @ErrorMessage; RAISERROR (@ErrorMessage, @ErrorSeverity, 1, @ErrorNumber, @ErrorSeverity, @ErrorState, @ErrorProcedure, @ErrorLine) 

你不能:只有引擎可以抛出小于50000的错误。你所能做的就是抛出一个看起来像它的exception…

请在这里看到我的答案

这里的提问者使用客户端交易做他想做的事情,我认为这有点愚蠢。

好的,这是一个解决方法… 🙂

 DECLARE @Error_Number INT BEGIN TRANSACTION BEGIN TRY INSERT INTO Test(Id, Name) VALUES (newID(),'Ashish') /* Column 'Name' has unique constraint on it*/ END TRY BEGIN CATCH SELECT ERROR_NUMBER() --RAISERROR (@ErrorMessage,@Severity,@State) ROLLBACK TRAN END CATCH 

如果你注意到catch块,它不会引发错误,而是返回实际的错误号(也会回滚事务)。 现在在.NET代码中,如果使用ExecuteScalar(),而不是捕获exception,则会得到所需的实际错误编号并显示相应的编号。

 int errorNumber=(int)command.ExecuteScalar(); if(errorNumber=<SomeNumber>) { MessageBox.Show("Some message"); } 

希望这可以帮助,

编辑: – 只是一个笔记,如果你想获得受影响的logging数量,并试图使用ExecuteNonQuery,上述解决scheme可能无法为您工作。 否则,我认为这将适合你所需要的。 让我知道。

在发生错误后停止存储过程中的执行并将错误callback到调用程序的方法是遵循每个可能对此代码引发错误的语句:

 If @@ERROR > 0 Return 

我很惊讶自己发现在一个存储过程中的执行可以在出现错误后继续 – 没有意识到这可能导致一些难以追踪的错误。

这种types的error handling并行(预.Net)Visual Basic 6.期待SQL Server 2012中的Throw命令。

鉴于你还没有搬到2012年,一种实现原始错误代码冒泡的方法是使用从catch块中(重新)抛出exception的文本消息部分。 请记住,它可以包含一些结构,例如,用于调用者代码的XML文本来parsing其catch块。

当您希望在事务中执行SQL语句并将错误提供给您的代码时,您还可以为这些scheme创build包装存储过程。

 CREATE PROCEDURE usp_Execute_SQL_Within_Transaction ( @SQL nvarchar(max) ) AS SET NOCOUNT ON BEGIN TRY BEGIN TRANSACTION EXEC(@SQL) COMMIT TRANSACTION END TRY BEGIN CATCH DECLARE @ErrorMessage nvarchar(max), @ErrorSeverity int, @ErrorState int SELECT @ErrorMessage = N'Error Number: ' + CONVERT(nvarchar(5), ERROR_NUMBER()) + N'. ' + ERROR_MESSAGE() + ' Line ' + CONVERT(nvarchar(5), ERROR_LINE()), @ErrorSeverity = ERROR_SEVERITY(), @ErrorState = ERROR_STATE() ROLLBACK TRANSACTION RAISERROR (@ErrorMessage, @ErrorSeverity, @ErrorState) END CATCH GO -- Test it EXEC usp_Execute_SQL_Within_Transaction @SQL = 'SELECT 1; SELECT 2' EXEC usp_Execute_SQL_Within_Transaction @SQL = 'SELECT 1/0; SELECT 2' EXEC usp_Execute_SQL_Within_Transaction @SQL = 'EXEC usp_Another_SP' 

从deviseangular度来看,抛出原始错误号码和自定义消息的exception点有什么意义? 它在一定程度上破坏了应用程序和数据库之间的接口契约。 如果您想捕获原始错误并在较高代码中处理它们,请不要在数据库中处理它们。 那么当你发现一个exception时,你可以把提交给用户的消息更改为你想要的任何东西。 我不会这样做,因为它使你的数据库代码嗯'不正确'。 正如其他人所说,你应该定义一套你自己的错误代码(50000以上),然后抛出它们。 然后,您可以与潜在的业务问题分开讨论完整性问题(“不允许重复值”) – “邮政编码无效”,“没有find符合条件的行”等等。