Stored procedures and error handling - sql

I have 10 stored procedures.
For example -
stored procedure fetches the rows from table A
then stored procedure runs and then third...
How can I do error handling in this.. for example I have to check with if first stored procedure executed successfully run second else throw error. If first executed successfully run second stored procedure if second runs successfully run third otherwise throw error.
ALTER PROCEDURE [dbo].[MASTER_PROCEDURE] AS
EXEC QRY_STEP3
EXEC QRY_STEP_3_1_1
EXEC OQRY_STEP_3_1_1

I would add logic to each of your subsidiary stored procedures to determine whether they have succeeded or not. eg test for existence of the temporary table. Then use a return value to indicate success of the proc. Typically this would be 0 for succes and non-zero for failure.
You would then call the procs from your master proc like this
DECLARE #ReturnValue INT
EXEC #ReturnValue = QRY_STEP1
IF(#ReturnValue = 0)
BEGIN
EXEC #ReturnValue = QRY_STEP2
END
ELSE
BEGIN
--REPORT ERROR
END
Using this approach, your master proc doesnt need to know about the inner workings of each child proc, and your master proc code will be cleaner and more readable.

use ##error.. Can be done like this
ALTER PROCEDURE [dbo].[MASTER_PROCEDURE] AS
EXEC QRY_STEP3
IF ##error =0
begin
EXEC QRY_STEP_3_1_1
else
begin
print "error in proc name"
return 1
End
if (##error=0)
Begin
EXEC OQRY_STEP_3_1_1
Else
print "error in proc name"
return 1
End
END
END

First to do this correctly you should use TRY CATCH blocks in the child packages. Those should return to the calling proc if there is an error. This way you can also return an error code to the calling proc if results are unexpected, such as a temp table with zero records which is not an error but which might make the subsequent procs fail.
Next, why are you using child procs at all? Honestly this is something that is probably better done in one proc. You say for instance that you are creating temp tables in one proc that you use in subsequent procs. To do this you need global temp tables. The problem is that global temp tables are not specific to the orginal connection that called them and thus two people trying to do this simluatnaeously might have their data mixedup. Whereas if you use one proc and local temp tables that can't happen.

Related

In nested stored procedures - how to safely continue run the calling procedure even if the inner procedure fails?

I have one scenario, where I have nested stored procedures. I want my main procedure to continue running even if the called procedure (it just have some logging in a table) didn't run successfully.
can you please help.
many thanks!
main Stored Procedure
exec testSP -- Inner SP
-- I want the following code of main SP to run even if the inner SP fails or there is sometime issues or anything that makes it to fail
code for the main SP
U can use try-catch inside your main stored procedure (and/or your testSP as well).
BEGIN TRY
EXEC testSP
END TRY
BEGIN CATCH
-- do something when an error occurs
SELECT ERROR_NUMBER(), ERROR_MESSAGE(), 'testSP'
END CATCH

How to stop sequence of SQL stored procedure execution if one among them fails?

Here is one scenario i came across,
- I have a SQL job which has around four SQL stored procedure
- These are getting executed sequentially one after another
- Now Case is : If any of the stored procedure fails or raise an exception, entire Job should get halt.
How I could do that ?
Make yourself a little procedure with something like this:
BEGIN TRY
DECLARE #Return INTEGER
-- Run first procedure
EXEC #Return = firstProcedure
IF (#Return <> 0)
BEGIN
-- Do some error handling
END
-- Run second procedure
EXEC #Return = secondProcedure
IF (#Return <> 0)
BEGIN
-- Do some error handling
END
-- etc...
END TRY
BEGIN CATCH
-- Do some error handling
END CATCH
Although there are several different ways to do this, I would suggest that you use the facilities in SQL Server Agent. Make each of the calls a separate step in the job.
This will allow you to move from one step to the next when successful. You'll also be able to use SQL Server Agent's logging and error handling mechanisms to determine the error and handle it.

Selecting from stored procedure output

I am trying to explore the possibility of selecting from a stored procedure.
Something like this
SELECT name
FROM exec msdb..sp_help_job
WHERE name = 'SampleJob'
I understand SQL Server - SELECT FROM stored procedure that a user-defined function or view can be used, but these are not options for me.
Reason being I am not able to run the following SQL statement due to permission limitations on AWS-RDS.
SELECT name as Jobs
FROM msdb..sysjobs
This leaves me with no choice but to use msdb..sp_help_job.
What I am ultimately trying to achieve is this "If job is not created, then run create job script". The reason I need to select from the stored procedure is to see if the job exists.
Appreciate any advice / directions.
If you want to create something, but are concerned that it might already exist, then use try/catch blocks.
begin try
exec dbo.sp_add_job . . .
end try
begin catch
print 'Error encountered . . . job probably already exists'
end catch;
To be honest, I haven't done this with jobs/job steps. However, this is one way of re-creating tables, views, and so on.
According to the documentation for sp_help_job on MSDN this stored procedure has a #job_name parameter and a simple return code (0 = success or 1 = failure).
If you set the #job_name parameter on your call to sp_help_job and get the return code you should be able to test the value of the return code to accomplish what you want.
Something like this should work:
DECLARE #return_value int
EXEC #return_value = msdb..sp_help_job #job_name = 'MyJobName'
-- #return_value = 1 means the specified #job_name does not exist
IF #return_value = 1
BEGIN
-- run create job script
END

Declaring stored procedures header and body separately

I'm writing stored procedures in SQL Server 2008. I need to create two procedures which will use each other.
Procedure A executes B and B executes A.
So I suppose I have to declare headers of procedures firstly. I've searched over internet but I can't find the answer how can I make it.
So, my question is: how can I declare header and body of stored procedure separately in SQL Server 2008?
You can't separate them but you can create a SP that calls another SP that not yet exist.
When you run this
create procedure TheFirst as
begin
exec TheSecond
end
and SP TheSecond does not exist you will get a message:
The module 'TheFirst' depends on the missing object 'TheSecond'. The
module will still be created; however, it cannot run successfully
until the object exists.
Update:
To avoid the messages you can first create an empty proc and add the code later in the script.
create procedure ProcB as
go
create procedure ProcA as
begin
exec ProcB
end
go
alter procedure ProcB as
begin
exec ProcA
end

TSQL make EXECUTE statement synchronous

I have two TSQL EXEC statements
EXECUTE (N'MyDynamicallyGeneratedStoredProcedure') -- return 0 on success
SELECT #errCode = ##ERROR ;
IF (#errCode = 0)
BEGIN
EXEC 'A Sql Statement using ##temptable created from first', #returnValue
END
How do I make the two EXEC's synchronous? ; Right now the second EXEC does not wait for the first EXECUTE to complete. I tried issuing a WaitFor Delay, It waits but the second EXEC statement is never returing back.
Thanks.
Update, Here is more info:
First execute creates a global temp table and populates it from a complex SELECT query.
Second EXEC is a CLR Stored Procedure that generates a dynamic SP, based on the variables from recently created and populated Global Temp table.
Now the second EXEC, complains that the Global Temp table is not found.
Update 2, Found the issue (And its me!!)
GBN (and others) was point blank on the answer. EXEC IS synchronous. The problem? My understanding of the problem itself.. I had mentioned
EXECUTE (N'MyDynamicallyGeneratedStoredProcedure') -- return 0 on success
It should have been:
1(a) EXECUTE (N'CreateMyDynamicStoredProcedure') -- return 0 on success
1(b) EXECUTE (N'MyDynamicStoredProcedure') -- return 0 on success
I missed that 1(b) was actually executed somewhere else and after step (2) .
(I should go get a life!!)
EXECUTE is sychronous. The 2nd one runs after the 1st one. Always.
Do you have multiple connections running the same code? You are using a global temp table that will be visible to all connections so it may look like asyncc execution...
As gbn's answer has pointed out, EXECUTE is synchronous.
The problem might be that your SQL Connection object within CRL stored procedure is not in the same context as your batch script. Your global temporary table should have been dropped after running EXECUTE (N'MyDynamicallyGeneratedStoredProcedure')
Make sure that you create your SQLConnection object by passing "context connection=true"
Here is the post answer where someone had a similar problem accessing temporary table since SQLConnection was not in the same connection context.
Accessing TSQL created #temp tables from CLR stored procedure. Is it possible?
If your second CRL stored procedure runs through a different connection, CRL sproc will not be able to access the global temp table since it should have been dropped.
Refer to this post on Global Temporary life cycle (when the gloal temp is dropped)
Deleting Global Temporary Tables (##tempTable) in SQL Server