Vous pouvez utiliser RAISERROR. De l'MSDN documentation sur RAISERROR:
BEGIN TRY
-- RAISERROR with severity 11-19 will cause execution to
-- jump to the CATCH block
RAISERROR ('Error raised in TRY block.', -- Message text.
16, -- Severity.
1 -- State.
);
END TRY
BEGIN CATCH
DECLARE @ErrorMessage NVARCHAR(4000);
DECLARE @ErrorSeverity INT;
DECLARE @ErrorState INT;
SELECT @ErrorMessage = ERROR_MESSAGE(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE();
-- Use RAISERROR inside the CATCH block to return
-- error information about the original error that
-- caused execution to jump to the CATCH block.
RAISERROR (@ErrorMessage, -- Message text.
@ErrorSeverity, -- Severity.
@ErrorState -- State.
);
END CATCH;
EDIT:
Ce n'est pas vraiment la même chose que C# 's throw
ou throw ex
. Comme @henrikstaunpoulsen souligne que vous n'obtenez pas le numéro d'erreur d'origine dans la nouvelle erreur (RAISERROR est limité dans quels numéros il peut utiliser). Vous devriez utiliser une sorte de convention et analyser l'information (si disponible) hors du message.
MSDN a un article Using TRY...CATCH in Transact-SQL et j'ai utilisé une partie du code pour créer le test ci-dessous:
use test;
GO
IF OBJECT_ID (N'usp_RethrowError',N'P') IS NOT NULL
DROP PROCEDURE usp_RethrowError;
GO
CREATE PROCEDURE usp_RethrowError AS
IF ERROR_NUMBER() IS NULL
RETURN;
DECLARE
@ErrorMessage NVARCHAR(4000),
@ErrorNumber INT,
@ErrorSeverity INT,
@ErrorState INT,
@ErrorLine INT,
@ErrorProcedure NVARCHAR(200);
SELECT
@ErrorNumber = ERROR_NUMBER(),
@ErrorSeverity = ERROR_SEVERITY(),
@ErrorState = ERROR_STATE(),
@ErrorLine = ERROR_LINE(),
@ErrorProcedure = ISNULL(ERROR_PROCEDURE(), '-');
SELECT @ErrorMessage =
N'Error %d, Level %d, State %d, Procedure %s, Line %d, ' +
'Message: '+ ERROR_MESSAGE();
RAISERROR
(
@ErrorMessage,
@ErrorSeverity,
@ErrorState,
@ErrorNumber, -- parameter: original error number.
@ErrorSeverity, -- parameter: original error severity.
@ErrorState, -- parameter: original error state.
@ErrorProcedure, -- parameter: original error procedure name.
@ErrorLine -- parameter: original error line number.
);
GO
PRINT 'No Catch'
DROP TABLE XXXX
PRINT 'Single Catch'
BEGIN TRY
DROP TABLE XXXX
END TRY
BEGIN CATCH
EXEC usp_RethrowError;
END CATCH;
PRINT 'Double Catch'
BEGIN TRY
BEGIN TRY
DROP TABLE XXXX
END TRY
BEGIN CATCH
EXEC usp_RethrowError;
END CATCH;
END TRY
BEGIN CATCH
EXEC usp_RethrowError;
END CATCH;
qui produit la sortie suivante:
No Catch
Msg 3701, Level 11, State 5, Line 3
Cannot drop the table 'XXXX', because it does not exist or you do not have permission.
Single Catch
Msg 50000, Level 11, State 5, Procedure usp_RethrowError, Line 25
Error 3701, Level 11, State 5, Procedure -, Line 7, Message: Cannot drop the table 'XXXX', because it does not exist or you do not have permission.
Double Catch
Msg 50000, Level 11, State 5, Procedure usp_RethrowError, Line 25
Error 50000, Level 11, State 5, Procedure usp_RethrowError, Line 25, Message: Error 3701, Level 11, State 5, Procedure -, Line 16, Message: Cannot drop the table 'XXXX', because it does not exist or you do not have permission.
est-il pas un problème avec cela, en ce que le numéro d'erreur est différent de l'exception originale? –
@henrikstaunpoulsen Oui, vous avez raison. Je ne pense pas que ce soit possible dans T-SQL ou d'une autre manière. J'ai mis à jour le poste avec plus d'informations sur ce point. – ongle
en SQL 2012 il y a le nouveau mot-clé THROW – sergiom