There is a subtle difference, as demonstrated below.
First setup the following:
CREATE TABLE TMP
( ROW_ID int NOT NULL,
ALTER TABLE TMP ADD CONSTRAINT PK_TMP PRIMARY KEY CLUSTERED (ROW_ID)
)
GO
CREATE PROC pTMP1
AS
BEGIN TRY
INSERT INTO TMP VALUES(1)
INSERT INTO TMP VALUES(1)
INSERT INTO TMP VALUES(2)
END TRY
BEGIN CATCH
DECLARE @ErrMsg varchar(max)= ERROR_MESSAGE(),
@ErrSev int = ERROR_SEVERITY(),
@ErrState int = ERROR_STATE()
RAISERROR (@ErrMsg, @ErrSev, @ErrState)
END CATCH
GO
CREATE PROC pTMP2
AS
INSERT INTO TMP VALUES(1)
INSERT INTO TMP VALUES(1)
INSERT INTO TMP VALUES(2)
GO
Now run the following:
SET NOCOUNT ON
DELETE TMP
exec pTMP1
SELECT * FROM TMP
DELETE TMP
exec pTMP2
SELECT * FROM TMP
SET NOCOUNT OFF
--Cleanup
DROP PROCEDURE pTMP1
DROP PROCEDURE pTMP2
DROP TABLE TMP
You should get the following results:
Msg 50000, Level 14, State 1, Procedure pTMP1, Line 12
Violation of PRIMARY KEY constraint 'PK_TMP'. Cannot insert duplicate key in object 'dbo.TMP'. The duplicate key value is (1).
ROW_ID
-----------
1
Msg 2627, Level 14, State 1, Procedure pTMP2, Line 4
Violation of PRIMARY KEY constraint 'PK_TMP'. Cannot insert duplicate key in object 'dbo.TMP'. The duplicate key value is (1).
The statement has been terminated.
ROW_ID
-----------
1
2
Notice that the TRY..CATCH version did not execute the third INSERT statement, whereas the pTMP2 proc did. This is because control jumps to CATCH as soon as the error occurs.
NOTE: The behaviour of pTMP2 is affected by the XACT_ABORT setting.
Conclusion
The benefit of using TRY..CATCH as demonstrated depends on how you manage your transaction boundaries.
- If you roll-back on any error, then the changes will be undone. But this doesn't eliminate side-effects such as addtional processing. NOTE: If a different session simultaneously queries
TMP using WITH(NOLOCK) it may even be able to observe the temporary change.
- However, if you don't intend rolling back a transaction, you may find the technique is quite important to prevent certain data changes being applied in spite of an earlier error.
CATCHthrowing a new exception so it actually seems to subtract value as far as I can see...