Exception in Nested/Child SP - sql

The problem is on SQL Server 2008
I have run into this unusual situation. The situation is like this. I have two separate SQL Server installations. Lets name them as
Installation-1
Installation-2
On Installation-1 lets say I have database called Database-1. And on Installation-2 I have other database called Database-2.
Database-1 has a SP called Parent_SP. Database-2 has two SPs called Child_SP_1 and Child_SP_2.
Installation-2 has been added as a linked server on Installation-1.
The Parent_SP on Database-1 calls Child_SP_1 which in turn calls Child_SP_2.
Now what happens is if there is an exception/error in Child_SP_1. I am able to catch it. However if the exception is raised at Child_SP_2. The exception never gets caught in Parent_SP.
I have no idea why such a behavior. Logically any exception should be raised eventually to parent SP. Which is not happening.
I've been trying to debug and create different scenarios but so far no luck.
Is there any reason why it should not work ?

Related

SQL Server: verbose error messages?

Is there some configuration option for MS SQL Server which enables more verbose error messages.
Specific example: I would like to see the actual field values of the inserted record which violates a constraint during an insert, to help track down a bug in stored procedures which I haven't been able to reproduce.
I don't believe there is any such option. There are trace flags that give more information about deadlocks, but I've never heard of one that gives more information on a constraint violation.
If you control the application that is causing the crash then extending it's handling (as Jenn suggested) to include parameter values etc. Once you have the parameter values you can get a copy of live setup on a non-live server and start debugging the issue.
For more options, can any of the users affected reliably reproduce the issue? If they can then you might be able to run a profiler trace to capture the actual statements / parameter values being sent to the database. Of course, if you can figure out the steps to reproduce the issue then you can probably use more traditional debugging methods...
You don't say what the constraint is, I'm assuming it is a fairly complex constraint. If so, could it be broken down into several constraints so you can get more of a hint about the problem with the data?
You could also re-write the constraint as a trigger which could then include more information in the error that it raises. Although this would obviously need testing before being deployed to a production server!
Personally, I would go with changing the error handling of the application. It is probably the less risky change.
PS The application that I helped write, and now spend my time supporting, logs quite a lot of data when an unhandled exception occurs. If it is during a save then our data access layer attaches the complete list of all commands that were being run as part of the save transaction including parameter values. This has proved to be invaluable on many occasions, including some when tracking down constraint violations.
In a stored proc, what I do to get better informatino in a complex SP about the errors is take advantage of the fact that table variables are not affected by a rollback. So I put the information I want to use to troubleshoot into table variables at the time I create it and then if I hit the catch block and rollback, after the rollback I insert the data from the table variable into an exception table along with some meta data like the datetime.
With some thought you can design an exception table that will capture what you need from just about any proc (for instance you could concatenate all the input variables into one field, you could put in the step number that failed (of course then you have to assign stepnumbers to a variable) or you could log every step along the awy and then the last one logged is the one it failed on. Belive me when you are looking at troubleshooting a 100 line SP, this can come in handy. If I have dymanic SQl inteh proc, I can log the SQL variable that contains the dynamic code that was run.
The beauty of this is now you don't have to try to reproduce the error, you know what the input parameters were and any other information you find useful. Yes it can take a bit of time to set up once, but once you do it is relatively easy to get in the habit of putting it into any complex proc that you will want to log errors on.
You might also want to set a an nongeneralized one if you want to return spefic data values of a select used for an insert or the result set of a select that would tell you waht what wopuld have been being updated or deleted. Then you would have that only if the proc failed. This is a little more work than the general exception table but may be needed in some complex cases.

How to detect that trigger fails after calling a stored procedure from .Net application?

We have a .NET application (VB / VS2010) and are calling many stored procedures on a SQL Server 2008 for database queries. We also have quite a few update/insert/delete triggers that are executed automatically once these stored procedures modify the database tables.
There are quite often situations when a stored procedure is called and it seems to perform ok as no error is raised and the .NET app continues as usual. However if I then look under the covers and perform the stored procedure call manually via SQL Server Client I see that a trigger that's executed right after the stored procedure fails, thus rolling back all changes.
So my question is: what's the best way to detect and pass through errors in our .NET --> stored procedure --> trigger scenario to know for sure in the .NET app that everything succeeded or not in case of an error?
Many thanks in advance,
Steve
Update: I am at home now and away from my desk (and the code base) for the weekend, so won't have a chance to check the very details of the stored procedures. Thanks so much for the answers given so far. I can have a look at the code again next week.
But in the meantime...
One question was about the version of MS SQL Server: it's 2008.
From what I know out of the top of my head we are calling the stored procedures (at least those that don't read data and "just" update, delete or insert data) in this manner:
Using connection As New SqlConnection("connectionString")
Dim command As New SqlCommand("EXEC STORED_PROCEDUR_ENAME), connection)
command.Connection.Open()
command.ExecuteNonQuery()
End Using
I think the assumption behind the code above is the expectation that if something fails within the stored procedure or a related trigger, that
command.ExecuteNonQuery()
would then fail. That might be my first problem, i.e. will I have to alter this code?
One question below was if I use ExecuteDataReader, so the answer is no, at least not so far...
I'll comment on the SQL specific questions and suggestions below.
I actually had the same issue today,
to solve it i used an output #msg and placed it after each function in the sproc.
SET #msg = 'Test print 1'
each section i added one so i know what ever the last number printed was where the sproc failed. I then went to the table where the trigger was failing and adjusted it until it printed the last number and passed.
You should check ##error after each statement, and return the error if one exists.
Here's a good article for you. Check out the section "Why is My Error Not Raised". It describes a scenario that could be your problem.
http://www.sommarskog.se/error-handling-II.html
You might also want to try turning XACT_ABORT on, so stored procedures would fail for most errors.
EDIT: Here's another link that might help explain this.
http://www.novicksoftware.com/tipsandtricks/tips-erorr-handling-in-a-stored-procedure.htm
You can either return an error from your procedure if you check ##error and find it != 0, or you can use RAISERROR, which will definitely result in an exception in calling code.
http://msdn.microsoft.com/en-us/library/ms178592.aspx
as you mention that you are using sql server 2008. this gives capacity to use try.. catch. here is the article.
http://msdn.microsoft.com/en-us/library/ms175976.aspx
Also look at this forum.
http://social.msdn.microsoft.com/Forums/eu/transactsql/thread/03eae70e-d478-44a7-90f3-8e1d27d9f22e
i think try..catch will do the job. also in .net side i would use following code.
try
{
// your stored procedure execution code.
}
Catch (sqlexception e)
{
// do something with sql exception.
}
try this scenario see if that solves your issue.

Oracle - Obtain the SQL as a string when an exception occurs

I am trying to get the SQL query to be returned from a database call, when the query fails to execute and the return cursor has a failure state. This query string will be used for logging purposes.
One way to do this is to hold a variable that contains the SQL query as a string, and then wrap each query in the PL/SQL block with the exception handler and if an exception arises, return the query string with the failure status to the UI component.
Is there a better way to do this? Does Oracle exception object or any other package support this feature?
This question seems like a duplicate for the thread: Obtain the Query/CommandText that caused a SQLException
However, I did not find a solution to the problem in that thread, and I would like to know if there are any new packages supported by Oracle that gives us the query string that caused the exception to occur.
When you are calling the database from an external language (Java, C#) you can probably do it, by implementing your own JDBC (or whatever) driver.
You would do so by delegating the real world to a normal driver, but whenever a statement is sent to the database you remember the statement and if causes an exception you create a new exception which also includes the sql statement (and possibly bind variables).
Note that this will only give you your statement. If you execute a stored procedure or cause a trigger to fire which in turn fails you only get the original statement not the one that actually failed.

Can SQL Server automatically log stored procedure errors

I have a database that I am working on with over 900 SP's. None of the SP's have any error handling. Is there a utility within SQL Server 2005 or 2008 that would automatically log the SP and the error into a table?
If the SPs are being called from code in a separate data layer, you could possibly add a global exception handler for that class. There is no 'global' error handling, per-se in sql server as far as stored procedures go - think about code - in code, if you had a gazillion classes, and there was no ineritance of any sort, you would have to implement error handling on each class separately. Sql server SPs have their own error handling, such as try-catch and ##error - look on books online, or http://www.codeproject.com/KB/database/ErrorHandling.aspx

How to get inner errors from try/catch clause in SQL Server

I am running a stored procedure in SQL Server 2008 inside a try/catch. The stored procedure and the stored procs it calls raise a few errors but in the try/catch you only get the last error from the stored procedure that you are running.
Is there a way/trick to be able to somehow catch ALL the errors generated by child stored proc calls while running a particular stored procedure? (assume that you have no access to any stored procedures so you can't modify where they can write the error, i.e. you can't just change all the stored procedures to stop raising errors and instead write them to some table and in your catch read from that table)
Here is a good resource for how to deal with error handling in SQL Server.
http://www.sqlservercentral.com/articles/Development/anerrorhandlingtemplatefor2005/2295/
However, some of the methods require that you have the ability to change the code in order to capture the errors. There is really no way of getting around this. You can't just ignore the error, keep processing, and then come around later to deal with the error. In most, if not all, languages, exceptions have to be dealt with at the time the exception was raised. T-SQL is no different.
I personally use a stored procedure to log any error whenever it occurs. Here is what I use:
CREATE PROCEDURE [dbo].[Error_Handler]
#returnMessage bit = 'False'
WITH EXEC AS CALLER
AS
BEGIN
INSERT INTO Errors (Number,Severity,State,[Procedure],Line,[Message])
VALUES (
ERROR_NUMBER(),
ERROR_SEVERITY(),
ERROR_STATE(),
isnull(ERROR_PROCEDURE(),'Ad-Hoc Query'),
isnull(ERROR_LINE(),0),
ERROR_MESSAGE())
IF(#returnMessage = 'True')
BEGIN
select Number,Severity,State,[Procedure],Line,[Message]
from Errors
where ErrorID = scope_identity()
END
END
If you have stored procs that are raising more than one error, they need to be replaced no matter what. You probably have data integrity errors in your database. That is a critical, "everything needs to stop right now until this is fixed" kind of issue. If you can't replace them and they were incorrectly written to allow processing to continue when an error was reached, then I know of no way to find the errors. Errors are not recorded unless you tell them to be recorded. If the stored procs belong to a product you bought from another vendor and that's why you can't change them, your best bet is to change to a vendor that actually understands how to program database code because there is no salvaging a product written that badly.
You wouldn't have a Java or c# methods raising error after error. Why do you expect SQL to allow this? An exception is an exception
If the DB Engine is throwing errors then you have problems.
What I've done before is to separate testing and checking code: find out what is wronf first and throw one exception If no errors, do your writes.