Writing SQL runtime/syntax errors to a text file - sql-server

I want to generate a text file if there are syntax or runtime errors in a SQL stored procedure.
For example, I want to create a text file with this information when the procedure is called and if the following error is generated:
Msg 8114, Level 16, State 5, Procedure sp_LoadKAD_UAT, Line 94 [Batch Start Line 94]
Error converting data type varchar to float.
I am not using any other front-end tools. I need the solution in SQL server.
I am using Microsoft SQL Server 2017
I have done research on TRY and catch blocks and ##Error but I have not got the solution yet.

Using Try Catch block you can handle the error message and insert into any Temporary table.
Declare #Catcherror as Table (Errornumber int, Errormessage varchar(100))
BEGIN TRY
Declare #num1 as int=1, #num2 as int = 0, #result as int
set #result= #num1/#num2
end TRY
BEGIN CATCH
insert into #Catcherror (Errornumber, Errormessage)
Select ERROR_NUMBER() as Errornumber, ERROR_MESSAGE() as Errormessage
end CATCH
Select * from #Catcherror

Related

How to trigger SQL Server database/table error messages from VB.net

I want to trigger SQL Server error messages while executing a stored procedure.
Example
Msg 547, Level 16, State 0, Line 1
The DELETE statement conflicted with the REFERENCE constraint "FK_TableX_$RateCard_Box". The conflict occurred in database "TestDB", table "dbo.TableX".
I want to know if this error trigger in procedure, how can I popup meaningful message to user.
I execute the SQL Server stored procedure from VB.net.
It is possible to use TRY CATCH statements and throw Message, Severity and State in CATCH statement:
BEGIN TRY
-- Your code here...
END TRY
BEGIN CATCH
DECLARE #Message varchar(MAX) = ERROR_MESSAGE(),
#Severity int = ERROR_SEVERITY(),
#State smallint = ERROR_STATE()
RAISERROR(#Message, #Severity, #State)
END CATCH

Error Handling in VBS third party program like SQL

I have to develop a WinCC Visual Basic Script management application. In this application I read an XML archive, and after that I put the information in a SQL database through a SQL INSERT query.
My problem is that I don't know how to do the error handling to view the SQL errors in VBScript MsgBox for example.
Activating the error handling with On Error Resume Next and after the evaluation of these errors with If Err.Number <> 0 Then ... the errors produced in SQL Server don't appear in VBScript.
If you want to get SQL Server error, You can use stored procedure with transaction to insert data into table:
create procedure dbo.InsertTable (
#param1 nvarchar(80)
,#param2 nvarchar(80)
,#error_text nvarchar(400) output)
as
begin
begin tran
begin try
insert into YourTable (column1, column2)
values (#param1, #param2)
end try
begin catch
set #error_text = error_message()
rollback
return
end catch
commit
end
Now You will get eventually error from the output parameter #error_text
declare #error_text nvarchar(400)
exec dbo.InsertTable 'Value1','Value2', #error_text output
select #error_text

Why the procedure is not going into the catch block

I have a stored procedure which is selecting the entry from the Entity table which doesn't exists in our database.
In the code below if I execute the stored procedure, it's not going into catch block while for every error in try block it should go to the catch block automatically.
I am not able to understand the reason
Create PROCEDURE AddUpdateEntity
(#Name VARCHAR(20),
#Age SMALLINT)
AS
BEGIN TRY
SELECT NAME, Age FROM Entity WHERE NAME = #name AND Age = #Age
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER() StatusCode, ERROR_MESSAGE() [Message]
END CATCH
GO
/* Command to execute the SP */
EXEC AddUpdateEntity 'Sandeep',20
This execute statement is showing the error "Invalid Entity Object" but not calling the catch block.
The stored procedure has crashed and is showing the message
Msg 208, Level 16, State 1, Procedure AddUpdateEntity, Line 10
Nom d'objet 'Entity' non valide.
As per the MSDN (follow link http://msdn.microsoft.com/en-us/library/ms175976.aspx)
Errors Unaffected by a TRY…CATCH Construct
TRY…CATCH constructs do not trap the following conditions:
Warnings or informational messages that have a severity of 10 or lower.
Errors that have a severity of 20 or higher that stop the SQL Server Database Engine task processing for the session. If an error occurs that has severity of 20 or higher and the database connection is not disrupted, TRY…CATCH will handle the error.
Attentions, such as client-interrupt requests or broken client connections.
When the session is ended by a system administrator by using the KILL statement.
The following types of errors are not handled by a CATCH block when they occur at the same level of execution as the TRY…CATCH construct:
Compile errors, such as syntax errors, that prevent a batch from running.
Errors that occur during statement-level recompilation, such as object name resolution errors that occur after compilation because of deferred name resolution.
These errors are returned to the level that ran the batch, stored procedure, or trigger.
If an error occurs during compilation or statement-level recompilation at a lower execution level (for example, when executing sp_executesql or a user-defined stored procedure) inside the TRY block, the error occurs at a lower level than the TRY…CATCH construct and will be handled by the associated CATCH block.
Hope the above description will solve your problem.
It will never enter the CATCH block simply because no rows are returned from a query. A sql query which returns no rows isn't an error; it's expected behavior.
As others have pointed out, the error you're seeing appears to be a compile-time error, because the Entity table does not exist.
You could try using dynamic sql with sp_executesql to force the SP to check for the tables existence only at run-time.
BEGIN TRY
DECLARE #sqlStr NVARCHAR(4000),
#sqlParams NVARCHAR(400);
SET #sqlStr = N'SELECT Name, Age FROM Entity WHERE Name=#Name AND Age=#Age';
SET #sqlParams = '#Name VARCHAR(20), #Age SMALLINT';
sp_executesql #sqlStr, #sqlParams, #Name = #Name, #Age = #Age
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER() StatusCode, ERROR_MESSAGE() [Message]
END CATCH

Error handling in Oracle stored procedure

Is it possible to know the line no. at which an error occurred inside an oracle or SQL server stored procedure?
In Oracle you can use
DBMS_UTILITY.FORMAT_ERROR_STACK to get the error stack and
DBMS_UTILITY.FORMAT_CALL_STACK to get the call stack.
Both return a varchar2(2000).
A nice example of the usage is here http://psoug.org/reference/exception_handling.html in Dan Morgans library.
There is a lot of info available and line numbers are amongst them.
In SQL Server, you can catch all of the attributes of the error.
BEGIN TRY
-- Generate a divide-by-zero error.
SELECT 1/0;
END TRY
BEGIN CATCH
SELECT
ERROR_NUMBER() AS ErrorNumber
,ERROR_SEVERITY() AS ErrorSeverity
,ERROR_STATE() AS ErrorState
,ERROR_PROCEDURE() AS ErrorProcedure
,ERROR_LINE() AS ErrorLine
,ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
GO
http://msdn.microsoft.com/en-us/library/ms175976.aspx
Better yet, create an error table and a stored procedure to insert these values into the table. Then execute the stored procedure in the catch block.
For SQL Server it will give you the line in the message tab when you run the proc from SQL Server Management Studio
For example, if you have this proc
CREATE PROCEDURE prTest
AS
SELECT 1
SELECT 2
SELECT bla FROM SOMETABLE
SELECT 3
GO
and you run it like this
EXEC prTest
you get this error message
Msg 208, Level 16, State 1, Procedure
prTest, Line 7 Invalid object name
'SOMETABLE'.
In your procedure you'll need to catch the exception. You can even send the exception to an error log table. How fun is that! Or, you could just DBMS_OUTPUT the message, but it might be pretty long. DBMS_OUTPUT has a limit on message sizes. Default is 20000 characters.
You can even create custom exceptions.
You'll first need a variable
EM VARCHAR(2000);
Then this at the end of your procedure.
EXCEPTION WHEN OTHERS THEN
EM := substr(SQLERRM, 1, 2000) ;
ROLLBACK;
INSERT INTO ERROR_LOG(ERROR_TIME, PROC_NAME , ERROR_MSG)
VALUES(SYSTIMESTAMP , 'PKG.get_stuff', EM);
COMMIT;
RETURN NULL;

SQL Server 2000: How to exit a stored procedure?

How can I exit in the middle of a stored procedure?
I have a stored procedure where I want to bail out early (while trying to debug it). I've tried calling RETURN and RAISERROR, and the sp keeps on running:
CREATE PROCEDURE dbo.Archive_Session #SessionGUID uniqueidentifier AS
print 'before raiserror'
raiserror('this is a raised error', 18, 1)
print 'before return'
return -1
print 'after return'
[snip]
I know it keeps running because I encounter an error further down. I don't see any of my prints. If I comment out the bulk of the stored procedure:
CREATE PROCEDURE dbo.Archive_Session #SessionGUID uniqueidentifier AS
print 'before raiserror'
raiserror('this is a raised error', 18, 1)
print 'before return'
return -1
print 'after return'
/*
[snip]
*/
Then I don't get my error, and I see the results:
before raiserror
Server: Msg 50000, Level 18, State 1, Procedure Archive_Session, Line 5
this is a raised error
before return
So the question is: how do I bail out of a stored procedure in SQL Server?
You can use RETURN to stop execution of a stored procedure immediately. Quote taken from Books Online:
Exits unconditionally from a query or
procedure. RETURN is immediate and
complete and can be used at any point
to exit from a procedure, batch, or
statement block. Statements that
follow RETURN are not executed.
Out of paranoia, I tried yor example and it does output the PRINTs and does stop execution immediately.
Unless you specify a severity of 20 or higher, raiserror will not stop execution. See the MSDN documentation.
The normal workaround is to include a return after every raiserror:
if #whoops = 1
begin
raiserror('Whoops!', 18, 1)
return -1
end
Put it in a TRY/CATCH.
When RAISERROR is run with a severity
of 11 or higher in a TRY block, it
transfers control to the associated
CATCH block
Reference: MSDN.
EDIT: This works for MSSQL 2005+, but I see that you now have clarified that you are working on MSSQL 2000. I'll leave this here for reference.
i figured out why RETURN is not unconditionally returning from the stored procedure. The error i'm seeing is while the stored procedure is being compiled - not when it's being executed.
Consider an imaginary stored procedure:
CREATE PROCEDURE dbo.foo AS
INSERT INTO ExistingTable
EXECUTE LinkedServer.Database.dbo.SomeProcedure
Even though this stord proedure contains an error (maybe it's because the objects have a differnet number of columns, maybe there is a timestamp column in the table, maybe the stored procedure doesn't exist), you can still save it. You can save it because you're referencing a linked server.
But when you actually execute the stored procedure, SQL Server then compiles it, and generates a query plan.
My error is not happening on line 114, it is on line 114. SQL Server cannot compile the stored procedure, that's why it's failing.
And that's why RETURN does not return, because it hasn't even started yet.
This works over here.
ALTER PROCEDURE dbo.Archive_Session
#SessionGUID int
AS
BEGIN
SET NOCOUNT ON
PRINT 'before raiserror'
RAISERROR('this is a raised error', 18, 1)
IF ##Error != 0
RETURN
PRINT 'before return'
RETURN -1
PRINT 'after return'
END
go
EXECUTE dbo.Archive_Session #SessionGUID = 1
Returns
before raiserror
Msg 50000, Level 18, State 1, Procedure Archive_Session, Line 7
this is a raised error
This seems like a lot of code but the best way i've found to do it.
ALTER PROCEDURE Procedure
AS
BEGIN TRY
EXEC AnotherProcedure
END TRY
BEGIN CATCH
DECLARE #ErrorMessage NVARCHAR(4000);
DECLARE #ErrorSeverity INT;
DECLARE #ErrorState INT;
SELECT
#ErrorMessage = ERROR_MESSAGE(),
#ErrorSeverity = ERROR_SEVERITY(),
#ErrorState = ERROR_STATE();
RAISERROR (#ErrorMessage, -- Message text.
#ErrorSeverity, -- Severity.
#ErrorState -- State.
);
RETURN --this forces it out
END CATCH
--Stuff here that you do not want to execute if the above failed.
END --end procedure
Its because you have no BEGIN and END statements. You shouldn't be seeing the prints, or errors running this statement, only Statement Completed (or something like that).

Resources