Async Stored Procedure Call in T-SQL - sql-server

How one can make an async call to a stored procedure from another one?
Assume I have two stored procedures, SP1 and SP2 (this is a long running stored procedure, takes much time to execute, and doesn't return any result).
The stored procedure SP1 is defined like this:
CREATE PROCEDURE SP1
AS
BEGIN
--custom business logic
--CALL to SP2, but async
EXEC SP2
END
How could you make a non-blocking/async call to SP like the above in SQL Server 2008/2012?

There was once I tried to achieve this by wrapping the stored procedure into Job, and then Calling the job in the procedure through sp_start_job system sp.
EXEC dbo.sp_start_job N'Job name' ;

Blockquote
Works as long as there are no arguments. – RoastBeast Dec 22 '15 at 17:30
Here's version with passing parameters
declare #variable -- job name
declare #command -- command
set #command = 'select * from table where data='+#variable
exec msdb..sp_add_job
#job_name =#variable,
#enabled=1,
#start_step_id=1,
#delete_level=1 --Job will delete itself after success
exec msdb..sp_add_jobstep
#job_name=#variable,
#step_id=1,
#step_name='step1',
#command=#command
exec msdb..sp_add_jobserver
#job_name = #variable,
#server_name = 'yourserver'
exec msdb..sp_start_job
#job_name=#variable

Related

Parameterize sp_add_jobstep for SSIS

From a TSQL Stored Procedure, I want to use the sp_add_jobstep stored procedure in the msdb database to create an SQL Agent job, which calls an SSIS package. I need to do this programmatically to dynamically set one of the parameters in the SSIS package at time of Job creation. In the "SQL Server Agent>Jobs>New Job" GUI, this is done under the "Steps>Edit>Configuration>Parameters" screen. How does one assign parameters with the sp_add_jobstep Stored Procedure?
The Microsoft documentation: https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-add-jobstep-transact-sql
does not explain this.
Related posts:
This post shows how to create an Agent job in T-SQL or C#: Create SQL Server Agent jobs programatically
And this post shows the SSIS syntax but does not discuss parameters: How do I create a step in my SQL Server Agent Job which will run my SSIS package?
As noted in the response by SAS, the params have to be passed as part of the command. The documentation for sp_add_jobstep shows a parameter called #additional_parameters, but notes this is not supported. So, while I didn't script it out (which would have been quicker), I did make an example job & then query the msdb.dbo.sysjobsteps table to see the format of the command. Based on that, and the earlier post by CSharper, I wrote the following stored procedure:
CREATE PROCEDURE [dbo].[CreateAgentjobHourlySSIS]
#job NVARCHAR(128),
#package NVARCHAR(max), -- \SSISDB\MyCatalog\MyProject\MyPackage.dtsx
#params NVARCHAR(max), -- /Par "\"$Project::MyParameter\"";ParameterValue /Par "\"$ServerOption::LOGGING_LEVEL(Int16)\"";1 /Par "\"$ServerOption::SYNCHRONIZED(Boolean)\"";True
#servername NVARCHAR(28),
#startdate DATE,
#starttime TIME,
#frequencyhours INT
AS
BEGIN TRY
BEGIN TRAN
--GRANT EXEC on CreateAgentjobHourlySSIS to PUBLIC
--1. Add a job
EXEC msdb.dbo.sp_add_job
#job_name = #job
--2. Add a job step named process step. This step runs the stored procedure
DECLARE #SSIScommand as NVARCHAR(max)
SET #SSIScommand = '/ISSERVER "\"'+#package+'\"" /SERVER "\"'+#servername+'\"" '+#params+' /CALLERINFO SQLAGENT /REPORTING E'
EXEC msdb.dbo.sp_add_jobstep
#job_name = #job,
#step_name = N'process step',
#subsystem = N'Dts',
#command = #SSIScommand
--3. Schedule the job starting at a specified date and time
DECLARE #startdateasint int = YEAR(#startDate)*10000+MONTH(#startdate)*100+DAY(#startdate)
DECLARE #starttimeasint int = DATEPART(HOUR,#starttime)*10000+DATEPART(MINUTE,#starttime)*100+DATEPART(SECOND,#starttime)
EXEC msdb.dbo.sp_add_jobschedule #job_name = #job,
#name = 'Hourly Schedule',
#freq_type = 4, --daily
#freq_interval = 1,
#freq_subday_type = 0x8, -- hourly
#freq_subday_interval = #frequencyhours,
#active_start_date = #startdateasint,
#active_start_time = #starttimeasint
--4. Add the job to the SQL Server
EXEC msdb.dbo.sp_add_jobserver
#job_name = #job,
#server_name = #servername
COMMIT TRAN
END TRY
BEGIN CATCH
SELECT ERROR_Message(), ERROR_Line();
ROLLBACK TRAN
END CATCH
You construct the call like this:
#command=N'/ISSERVER "
...
/Par "\"$Project::MyParam\"";ParamValue
...
If you already have a similar job you can right-click in SSMS and script it out.
That will show you the syntax.

How to start SQL Server job from a stored procedure?

How can I create a stored procedure to start a SQL Server job?
-- Create SQL Server Agent job start stored procedure with input parameter
CREATE PROC uspStartMyJob #MyJobName sysname
AS
DECLARE #ReturnCode tinyint -- 0 (success) or 1 (failure)
EXEC #ReturnCode=msdb.dbo.sp_start_job #job_name=#MyJobName;
RETURN (#ReturnCode)
GO
OR with no parameter:
-- Create stored procedure to start SQL Server Agent job
CREATE PROC StartMyMonthlyInventoryJob
AS
EXEC msdb.dbo.sp_start_job N'Monthly Inventory Processing';
GO
-- Execute t-sql stored procedure
EXEC StartMyMonthlyInventoryJob
EDIT FYI: You can use this PRIOR to starting IF you don't want to start the job IF it is running currently, work this in your stored proc:
-- Get run status of a job
-- version for SQL Server 2008 T-SQL - Running = 1 = currently executing
-- use YOUR guid here
DECLARE #job_id uniqueidentifier = '5d00732-69E0-2937-8238-40F54CF36BB1'
EXEC master.dbo.xp_sqlagent_enum_jobs 1, sa, #job_id
You can execute the stored procedure sp_start_job in your stored procedure.
See here: http://msdn.microsoft.com/en-us/library/ms186757.aspx
Create your store procedure and run the job inside your proc as follows:
DECLARE #JobId binary(16)
SELECT #JobId = job_id FROM msdb.dbo.sysjobs WHERE (name = 'JobName')
IF (#JobId IS NOT NULL)
BEGIN
EXEC msdb.dbo.sp_start_job #job_id = #JobId;
END

Use database inside a stored procedure

I need to make a stored procedure which creates a user in more than one database. Something like this:
USE [database1]
CREATE USER [userLogin] FOR LOGIN [userLogin]
USE [database2]
CREATE USER [userLogin] FOR LOGIN [userLogin]
Since the CREATE USER statement does his job in the current database I need to use the USE statement to change between databases, but it can't be used inside stored procedures.
How can I do this?
Dynamic SQL
CREATE PROCEDURE spTestProc
AS
EXEC ('USE [database1]; CREATE USER [userLogin] FOR LOGIN [userLogin]')
EXEC ('USE [database2]; CREATE USER [userLogin] FOR LOGIN [userLogin]')
GO
SQL Server gives us a system stored procedure to do this. My understanding is that the recommended method would be to use sys.sp_grantdbaccess:
CREATE PROCEDURE usp_CreateTwoUSers
AS
BEGIN
-- Create a user for a login in the current DB:
Exec sp_grantdbaccess [userLogin], [name_in_db];
-- Create a user for a login in an external DB:
Exec ExternalDatabaseName.sys.sp_grantdbaccess [userLogin], [name_in_db];
END
I did it like below:
Alter Procedure testProc
#dbName varchar(50)
As
declare #var varchar(100)
set #var = 'Exec(''create table tableName(name varchar(50))'')'
Exec('Use '+ #dbName + ';' + #var)
Exec testProc 'test_db'
CREATE PROCEDURE spTestProc
AS
BEGIN
EXECUTE sp_executesql N'USE DB1 SELECT * FROM TABLE1'
EXECUTE sp_executesql N'USE DB2 SELECT * FROM Table2'
END
exec spTestProc
now it is worked.
If you're writing dynamic SQL with EXEC sp_executesql ('query1') or EXEC ('query2') this will return correct db which you want. If you're writing static SQL or your query outside of dynamic SQL quotes or parantheses it will work on master (where you create stored procedure(default is master)).
CREATE PROCEDURE master.dbo.mysp1
AS
EXEC ('USE model; SELECT DB_NAME()') -- or sp_executesql N'USE model; SELECT DB_NAME()'
--this returns 'model'
GO
CREATE PROCEDURE master.dbo.mysp2
AS
EXEC ('USE model;') -- or sp_executesql N'USE model;'
SELECT DB_NAME()
-- this returns 'master'
GO
It should be noted that if you want to use single quotes within a EXEC command, you will need to double the amount of single quotes
e.g.
EXEC ('USE [database1]; select * from Authors where name = ''John'' ')
In this example, John has 2 single quotes before and after it.
You cannot use double quotes for this type of query.
Using sp_executesql seems to work, for more info see http://msdn.microsoft.com/en-us/library/ms175170.aspx
I tested it using this and it worked fine:
CREATE PROCEDURE spTestProc
AS
BEGIN
EXECUTE sp_executesql N'USE DB1;'
SELECT * FROM TABLE1
EXECUTE sp_executesql N'USE DB2;'
SELECT * FROM Table2
END
exec spTestProc

How to call a stored procedure inside the other stored procedure

I have created a stored procedure in SQL Server 2005, also I create another stored proc (that accepts some input parameters), I have to invoke with the use of the first proc.
CREATE PROCEDURE prc_inner (#value INT)
AS
SELECT #value
GO
CREATE PROCEDURE prc_outer (#value INT)
AS
EXEC prc_inner #value
GO
EXEC prc_outer 1
Look up EXEC sp_executesql or just plain EXEC [storedprocedurename]

Execute a SProc from within a Sproc (using params passed in)

Does anyone know of a way to execute a stored procedure from within a stored procudure using some of the params passed in from the original procedure.
i.e.
if i pass in params #id, #event date, # log into sproc 1
then sproc 1 will do it's own stuff and pass in #log and #event_date to sproc 2.
Thanks!
just call:
exec mysproc #param1 #param2
inside your sproc.
Just execute the second sp the same way you would have from a query.
EXEC SPROC2 #LOG, #EVENT_DATE
call exec with the parameters of interest:
... within sp_1
... other code
exec sp_2 #log, #event_date

Resources