Reputation: 353
I have a simple stored procedure shown below. As you can see, the error is forcefully generated inside the dynamic SQL and passed to the CATCH block. The problem is that the details I expect are not returned. All I get back is this message:
Msg 50000, Level 16, State 1, Procedure myproc, Line 35 [Batch Start Line 2]
Why don't I get back the information as coded in the CATCH block - procedure name, error line and error message?
Here is my procedure:
CREATE PROCEDURE myproc
AS
SET XACT_ABORT ON
BEGIN TRY
DECLARE @nSQL NVARCHAR(MAX) = 'SELECT 1/0'
EXEC sp_executesql @nSQL
END TRY
BEGIN CATCH
DECLARE @ERROR_NUMBER INT;
DECLARE @ERROR_SEVERITY INT;
DECLARE @ERROR_STATE INT;
DECLARE @ERROR_PROCEDURE NVARCHAR(128);
DECLARE @ERROR_LINE INT;
DECLARE @ERROR_MESSAGE NVARCHAR(4000);
SET @ERROR_NUMBER = ERROR_NUMBER();
SET @ERROR_SEVERITY = ERROR_SEVERITY();
SELECT @ERROR_STATE = CASE
WHEN ERROR_STATE() = 0 THEN 1
ELSE ERROR_STATE()
END;
SET @ERROR_PROCEDURE = ERROR_PROCEDURE();
SET @ERROR_LINE = ERROR_LINE();
SET @ERROR_MESSAGE = 'ERROR in ' + @ERROR_PROCEDURE + '; (ERROR Line: ' + CAST(@ERROR_LINE AS NVARCHAR(5)) + '); ' + 'ERROR MESSAGE: '
+ ERROR_MESSAGE() + ';';
RAISERROR(@ERROR_MESSAGE, @ERROR_SEVERITY, @ERROR_STATE);
RETURN (1);
END CATCH;
Upvotes: 1
Views: 2177
Reputation: 158
If you are using SQL Server 2012 or above version, it is recommended to use THROW.
Changing your whole CATCH block to below should be enough:
BEGIN CATCH
THROW
END CATCH;
Msg 8134, Level 16, State 1, Line 1
Divide by zero error encountered.
Upvotes: 0
Reputation: 37472
"ERROR_PROCEDURE (Transact-SQL)":
ERROR_PROCEDURE
returnsNULL
if the error did not occur within a stored procedure or trigger.
Since the dynamic SQL is not a procedure nor a trigger, this applies here and your @ERROR_PROCEDURE
is NULL
.
Now you use @ERROR_PROCEDURE
in a string concatenation using +
and assign that to @ERROR_MESSAGE
. If you lookup the remarks in "+ (String Concatenation) (Transact-SQL)", you'll see that this can lead to the result of the concatenation being NULL
and that likely happens in your case.
When you work with strings with a null value, the result of the concatenation depends on the session settings. Just like arithmetic operations that are performed on null values, when a null value is added to a known value the result is typically an unknown value, a string concatenation operation that is performed with a null value should also produce a null result. However, you can change this behavior by changing the setting of
CONCAT_NULL_YIELDS_NULL
for the current session.
So you pass a NULL
as the first argument for RAISERROR
and therefore no message is printed.
You can use concat()
instead of +
for the concatenation or replace NULL
s manually.
But you should avoid RAISERROR
anyway. See the note in "RAISERROR (Transact-SQL)".
The
RAISERROR
statement does not honorSET XACT_ABORT
. New applications should useTHROW
instead ofRAISERROR
.
Upvotes: 1
Reputation: 46203
ERROR_PROCEDURE()
is NULL
because the error occurred in the inner scope of the dynamic SQL statement, not in the stored procedure itself. If you want the name of the current proc, use OBJECT_NAME(@@PROCID)
.
Upvotes: 1