Reputation: 815
I have the following code:
BEGIN TRY
EXEC (@action_sql);
END TRY
BEGIN CATCH
SELECT @change_id AS ChangeId,
@action_sql AS sqlAttempted,
ERROR_MESSAGE () AS ErrorMessage,
ERROR_NUMBER () AS ErrorNumber,
ERROR_SEVERITY () AS ErrorSeverity,
ERROR_LINE () AS ErrorLine;
END CATCH;
IF @@ERROR = 0
BEGIN
PRINT '@@ERROR = ' + CAST (@@ERROR AS VARCHAR (10))
PRINT 'COMMIT';
COMMIT TRANSACTION;
END
ELSE
BEGIN
PRINT '@@ERROR = ' + CAST (@@ERROR AS VARCHAR (10))
PRINT 'ROLLBACK';
ROLLBACK TRANSACTION;
END;
When I put a valid or invalid SQL statement in @action_sql
I always get printed
@@ERROR = 0
COMMIT
@@ERROR
always returns zero even if action_sql
is invalid.
What is the easiest way to determine if some sort of error took place?
Thanks,
Upvotes: 0
Views: 3081
Reputation: 69554
The @@ERROR
function is populated as soon as an error occurs and if there is any other statement executing after this function its values is reset to NULL
so you have to use a variable to capture the value of @@ERROR function after you have executed your statement,
So to anticipate where an error can occur and then Store its value to a Variable is really an over kill when you have TRY..CATCH
blocks.
Since you are using TRY..CATCH
blocks, you really dont need to use @@ERROR function. just change the order of your code a little bit.
something like this...
BEGIN TRY
BEGIN TRANSACTION
EXEC (@action_sql); --<-- if an error occurs here control jumps to catch block and
-- following lines of code never gets executed. (I mean in case of an error)
PRINT 'COMMIT';
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
IF @@TRANCOUNT <> 0 --<-- Once an error occurred check for any open trans
ROLLBACK TRANSACTION -- if there is one ROLLBACK it.
SELECT @change_id AS ChangeId, --<-- Rest of the ERROR Functions
@action_sql AS sqlAttempted,
ERROR_MESSAGE () AS ErrorMessage,
ERROR_NUMBER () AS ErrorNumber,
ERROR_SEVERITY () AS ErrorSeverity,
ERROR_LINE () AS ErrorLine;
END CATCH;
Now since you have BEGIN
an Explicit Transaction
in your TRY
block if any error occurs the executing will stop there and the control will jump to CATCH
block.
Then there you can check for any OPEN TRANSACTIONs using @@TRANCOUNT
and if open just roll back it and get all the other info about the error using ERROR MESSAGES.
Upvotes: 2
Reputation: 20955
It's because the value for @@ERROR
is getting reset to 0
i.e. no error after you've captured and handled it in your TRY CATCH
block. So the right way to do this is to capture and store the error values (if any) in variables, and then use those variables to take further action based on whether or not the variables indicate that an error happened.
See sample code below. The @action_sql
is invalid in 1st case, and you will see the error code printed out. In the second case, the @action_sql
is valid and you won't see any error code printed out.
1st Sample: Invalid @action_sql
.
declare @action_sql NVARCHAR(2000);
declare @change_id INT
declare @ErrorNumber int
declare @ErrorMessage NVARCHAR(2000);
set @action_sql = 'select * from sysobj;'
BEGIN TRY
EXEC (@action_sql);
END TRY
BEGIN CATCH
SELECT
@ErrorMessage = ERROR_MESSAGE(),
@ErrorNumber = ERROR_NUMBER()
-- ERROR_SEVERITY () AS ErrorSeverity,
-- ERROR_LINE () AS ErrorLine;
END CATCH;
IF @ErrorNumber = 0
BEGIN
PRINT '@@ERROR = ' + CAST (@ErrorNumber AS VARCHAR (10))
PRINT 'COMMIT';
--COMMIT TRANSACTION;
END
ELSE
IF (@ErrorNumber > 0)
BEGIN
PRINT '@@ERROR = ' + CAST (@ErrorNumber AS VARCHAR (10))
PRINT 'ROLLBACK';
--ROLLBACK TRANSACTION;
END;
2nd Sample: Valid @action_sql
declare @action_sql NVARCHAR(2000);
declare @change_id INT
declare @ErrorNumber int
declare @ErrorMessage NVARCHAR(2000);
set @action_sql = 'select top 10 * from sysobjects;'
BEGIN TRY
EXEC (@action_sql);
END TRY
BEGIN CATCH
SELECT
@ErrorMessage = ERROR_MESSAGE(),
@ErrorNumber = ERROR_NUMBER()
-- ERROR_SEVERITY () AS ErrorSeverity,
-- ERROR_LINE () AS ErrorLine;
END CATCH;
IF @ErrorNumber = 0
BEGIN
PRINT '@@ERROR = ' + CAST (@ErrorNumber AS VARCHAR (10))
PRINT 'COMMIT';
--COMMIT TRANSACTION;
END
ELSE
IF (@ErrorNumber > 0)
BEGIN
PRINT '@@ERROR = ' + CAST (@ErrorNumber AS VARCHAR (10))
PRINT 'ROLLBACK';
--ROLLBACK TRANSACTION;
END;
Upvotes: 5