I was wondering if it's possible to retrieve the results of a stored procedure using another stored procedure.
I have the following as a test example
The first stored procedure is intended to return two values
if(object_id('sp_function01')) is not null
drop procedure sp_function01
go
create procedure sp_function01
as
declare #lv_res01 char(20)
declare #lv_res02 char(20)
set #lv_res01 = 'fn01 result 01'
set #lv_res02 = 'fn01 result 02'
select #lv_res01, #lv_res02
go
Then the second is intended to retrieve those values and utilize them
if(object_id('sp_function02')) is not null
drop procedure sp_function02
go
create procedure sp_function02
as
declare #lv_var01 char(20)
declare #lv_res01 char(20)
declare #lv_res02 char(20)
set #lv_var01 = 'variable 01'
exec sp_function01
-- catch variables from this function
-- into lv_res01 and lv_res02
select #lv_var01, #lv_res01, #lv_res02
go
Yet the values for lv_res01 and lv_res02 are NULL and I'm not sure how to actually catch them
Something like this:
First procedure:
create procedure sp_function01
#lv_res01 char(20) OUTPUT,
#lv_res02 char(20) OUTPUT
as
set #lv_res01 = 'fn01 result 01'
set #lv_res02 = 'fn01 result 02'
select #lv_res01, #lv_res02
go
Second procedure:
create procedure sp_function02
as
declare #lv_var01 char(20)
declare #lv_res01 char(20)
declare #lv_res02 char(20)
set #lv_var01 = 'variable 01'
exec sp_function01 #lv_res01 OUTPUT, #lv_res02 OUTPUT
-- catch variables from this function
-- into lv_res01 and lv_res02
select #lv_var01, #lv_res01, #lv_res02
go
Calling sp_function01 alone (it's more or less same you just need to declare all output parameters and pass them to proc whether from inside another stored procedure or outside of it):
DECLARE #lv_res01 char(20)
DECLARE #lv_res02 char(20)
exec sp_function01 #lv_res01 OUTPUT, #lv_res02 OUTPUT
The scope of local variables is the module in which they are declared so the variables in function02 are not available in function one. You need to either use OUTPUT parameters or use the INSERT...EXEC to insert the result set of function02 into a temp table or table variable.
See how to share data between stored procedures for a thorough discussion of these and other options.
Related
I've got a procedure call that is used by several groups/processes etc.
The call works as follows:
EXEC LWP_PAYMENT_URL #order_no, #dept
and it returns a string like this
NzI2NzU4NabNzEyMj24Ny1zYQ=
I'm given the assignment to create a url path as follows
DECLARE #url_path VARCHAR(4000)
SET #url_path = 'https://www.website.com/payment?code='
DECLARE #ReturnValue VARCHAR(4000) = ''
EXEC #ReturnValue = LWP_PAYMENT_URL #order_no, #dept
SET #url_path = #url_path + #ReturnValue
SELECT #ReturnValue, #url_path
My goal is to take the hard coded url_path and get the encoded string from the execute and save it in a variable and concatenate it to the url_path.
What I'm seeing is that the string is returned part of the execute call instead of setting it to #ReturnValue and then looks like I get a zero value being saved and concatenated.
Added these are the final two lines of the LWP_PAYMENT_URL procedure.
DECLARE #Encoded VARCHAR(500) = CONVERT(VARCHAR(500), (SELECT CONVERT(VARBINARY, #string) FOR XML PATH(''), BINARY BASE64))
SELECT #Encoded AS [Encoded]
Thank you
Your stored procedure should be doing this instead:
CREATE OR ALTER PROCEDURE dbo.LWP_PAYMENT_URL
...#input parameters...,
#encoded varchar(500) = NULL OUTPUT
AS
BEGIN
SET NOCOUNT ON;
...
SET #Encoded = CONVERT(varchar(500),
(SELECT CONVERT(VARBINARY, #string) FOR XML PATH(''), BINARY BASE64));
END
And then the caller says:
DECLARE #ReturnValue varchar(500);
EXEC dbo.LWP_PAYMENT_URL #order_no, #dept,
#Encoded = #ReturnValue output;
If you can't change the stored procedure, create a separate one, or a table-valued UDF as suggested in the comments, or (assuming there are no other SELECTs in the procedure we can't see):
CREATE TABLE #foo(ReturnValue varchar(500));
INSERT #foo EXEC dbo.LWP_PAYMENT_URL ...;
DECLARE #ReturnValue varchar(500);
SELECT #ReturnValue = ReturnValue FROM #foo;
That's gross, though, and basically an abuse of how data sharing should work in SQL Server.
Ideally what you should do is, if the logic is the same for all uses, put that logic in some type of module that is much easier to reuse (e.g. a table-valued function). Then this existing stored procedure can maintain the current behavior (except it would call the function instead of performing the calculation locally), and you can create a different stored procedure (or just call the function directly, if this is all your code is doing), and the logic doesn't have to be duplicated, and you don't have to trample on their stored procedure.
I've created a T-SQL script which works very well when I execute it directly. Then I've put this script into a stored procedure with 2 parameters but when I execute it, there is no rows affected... then I've found my 2 parameters are always received as NULL by my stored procedure.
I've tried to set default parameters values inside the create stored procedure script, but even that way, they are NULL.
I've tried to not declare the parameters as scalar variable inside the #SQLString since they already are created with the CREATE PROCEDURE as parameters but I got the error :
The scalar variable must be declared
when I tried to execute my stored procedure.
CREATE PROCEDURE [dbo].[sp_InsertMetierEventRelation]
#metier NVARCHAR(50),
#evenement NVARCHAR(50)
AS
BEGIN
SET NOCOUNT ON;
DECLARE #SQLString NVARCHAR(4000)
SET #SQLString = N'
DECLARE #rowId INT, #metier NVARCHAR(50), #evenement NVARCHAR(50)
SELECT #metier AS metierParam -- always NULL
SELECT #evenement AS evenementParam -- always NULL
SELECT met_id FROM [dbo].[t_metier] WHERE [met_nom] = #metier
SELECT eve_id FROM [dbo].[t_evenement] WHERE [eve_nom] = #evenement
-- some other code
'
EXECUTE sp_executesql #SQLString
END
GO
I call my stored procedure this way :
EXEC [dbo].[sp_InsertMetierEventRelation]
#metier = 'Organisation de mariage',
#evenement = 'Evènement religieux';
or this way :
EXEC [dbo].[sp_InsertMetierEventRelation]
'Organisation de mariage', 'Evènement religieux';
I got the same result :
metierParam NULL
evenementParam NULL
met_id NO RESULT
eve_id NO RESULT
Do you need dynamic SQL? What happens if you simplify it as:
CREATE PROCEDURE [dbo].[sp_InsertMetierEventRelation]
#metier NVARCHAR(50),
#evenement NVARCHAR(50)
AS
SELECT met_id FROM [dbo].[t_metier] WHERE [met_nom] = #metier
SELECT eve_id FROM [dbo].[t_evenement] WHERE [eve_nom] = #evenement
And then run the EXEC [dbo].[sp_InsertMetierEventRelation] ...
If you do need dynamic SQL then see answer from John Cappelletti.
I have one stored procedure which return a nvarchar value written like that:
ALTER PROCEDURE [dbo].[GetLastVouchNumber]
#returnVal nvarchar(255) output
AS
BEGIN
SET #returnVal = ( SELECT CONCAT('I',VOUCHNO+1)
FROM TABVOU
WHERE VOUCHER = 'VOUCHER#')
END
I am trying to use the output value from this procedure in another procedure. And this was how I try to write this new procedure:
ALTER PROCEDURE [dbo].[MassAdjInsertIntoYTDTRNI]
#inputPeriod nvarchar(255),
#inputUserId nvarchar(255)
AS
BEGIN
DECLARE #resultOrdNo nvarchar (255)
DECLARE #newOrdNo nvarchar(255)
EXEC #newOrdNo = GetLastVouchNumber #resultOrdNo
INSERT INTO YTDTRNI(TRCDE,PROD,WH,DESCR,UCOST,TCOST,DRAC,CRAC,REM,QTY,UM,ORDNO,TRDATE,SYSDATE,PERIOD,USERID)
SELECT 'AJ',PROD,WH,DESCR,0,-TCOST,STKGL,COSGL,'MASS ADJUSTMENT',0,UM,#newOrdNo, GETDATE(),GETDATE(),#inputPeriod,#inputUserId
FROM INV
I was assuming that this line:
EXEC #newOrdNo = GetLastVouchNumber #resultOrdNo
will store the result of the first procedure into #newOrdNo then after that I can use this #newOrdNo to insert it into another table. But after I execute this second stored procedure, the ORDNO column does not contain any values...
Need advice.
Use OUTPUT keyword when you call GetLastVouchNumber and pass #newOrdNo as an output parameter. Your GetLastVouchNumber procedure returns information with output parameter.
ALTER PROCEDURE [dbo].[MassAdjInsertIntoYTDTRNI]
#inputPeriod nvarchar(255),
#inputUserId nvarchar(255)
AS
BEGIN
DECLARE #resultOrdNo nvarchar (255)
DECLARE #newOrdNo nvarchar(255)
-- Call your stored procedure
EXEC GetLastVouchNumber #newOrdNo OUTPUT
INSERT INTO YTDTRNI(TRCDE,PROD,WH,DESCR,UCOST,TCOST,DRAC,CRAC,REM,QTY,UM,ORDNO,TRDATE,SYSDATE,PERIOD,USERID)
SELECT 'AJ',PROD,WH,DESCR,0,-TCOST,STKGL,COSGL,'MASS ADJUSTMENT',0,UM,#newOrdNo, GETDATE(),GETDATE(),#inputPeriod,#inputUserId
END
You seemed to have confused a return value and an output variable. Your stored proc uses the latter for returning your value, and does not explicitly return anything (Albeit confusing, as you have named your output variable returnVal).
When you call it, you must specify the OUTPUT
EXEC GetLastVouchNumber #resultOrdNo OUTPUT
I know this is a basic question - but I can't figure the correct way to get this done.
I need to pass a variable to a SQL Server 2008 stored procedure and return the query.
Here's the stored procedure:
CREATE PROCEDURE pOrders
AS
DECLARE #enteredClientID varchar(20);
DECLARE #Results table (ClientID varchar(20), Num_orders int);
BEGIN
SET NOCOUNT ON;
-- Get all the order from the client
INSERT INTO #Results
SELECT ClientID, sum(Num_orders)
FROM Orders O
WHERE O.ClientID = #enteredClientID
GROUP BY O.ClientID);
-- Insert the orders into the results table --
SELECT *
FROM #Results;
END
GO;
Now, I would execute the stored procedure and get the result back:
exec pOrders
set #enteredClientID = 'ABC123456789'
I get this error message back:
Must declare the scalar variable "#enteredClientID".
But, I'm declaring the variable.... what am I missing?
You didn't declare a parameter, but a local variable. To declare it as you wanted to:
CREATE PROCEDURE pOrders (#enteredClientID varchar(20))
AS
DECLARE #Results table (ClientID varchar(20), Num_orders int);
SET NOCOUNT ON;
-- Get all the order from the client
INSERT INTO #Results
SELECT ClientID, sum(Num_orders)
FROM Orders O
WHERE O.ClientID = #enteredClientID
GROUP BY O.ClientID);
-- Insert the orders into the results table --
SELECT *
FROM #Results;
GO;
An to call it:
exec pOrders #enteredClientID = 'ABC123456789'
or simply
exec pOrders 'ABC123456789'
--In stored proc
DECLARE #enteredClientID varchar(20) OUTPUT
--Then insert and set identity
SELECT SCOPE_IDENTITY() AS #enteredClientID
--When calling procedure:
-- DECLARE variables to hold the return value
DECLARE #enteredClientID VARCHAR(20);
-- Execute the procedure, which returns value.
EXEC #enteredClientID = pOrders
Try EXEC pOrders 'ABC123456789'.
The call you provided attempts to execute the procedure (with no parameters passed), then attempts to set a variable named #enteredClientID. Since you have not declared #enteredClientID in the scope of the executing code, it cannot set it.
For more information about how to use parameters with procedures, this article may be helpful:
http://msdn.microsoft.com/en-us/library/ms189915.aspx
I'm trying to call a stored procedure, the name of which is provided by looping through a table. The stored procedure is in another database.
However, I keep getting the message
Procedure or function 'sp_KPI_People_Added_Count' expects parameter
'#Period', which was not supplied.
But it is being supplied.
I have set the statement and parameter definition to NVarChar and prefixed them with N. I've also tried this on the parameters themselves but apparently that's not required.
All the print output is as expected and if I call an execute with the text, it works fine.
So I'm stuck. Any pointers would be warmly welcomed.
Thanks,
Chris.
Declare #KPI_Value Decimal(14,4)
Declare #StoredProcedure NVarChar(200)
Declare #Periodic Char(1)
Declare #ExecSql NVarChar(200)
Declare #ParameterDefinition AS NVarChar(200)
Declare KPI_Cursor CURSOR LOCAL FOR
SELECT SProc, Periodic from KPI where Section = 2
FOR UPDATE OF Current_Value
Open KPI_Cursor
Fetch Next From KPI_Cursor into #StoredProcedure, #Periodic
Declare #Required_Period VARCHAR(5)
SET #Required_Period='MTD'
While ##FETCH_STATUS = 0 BEGIN
Set #KPI_Value = 0 -- Have tried with and without this
If #Periodic = 'Z' BEGIN
SET #ExecSQL = N'Prod.dbo.' + #StoredProcedure;
/* Specify Parameter Format */
SET #ParameterDefinition = N'#Period VarChar(5), #Result_Type VarChar(10), #Result Decimal(14,4) OUTPUT';
/* Execute Transact-SQL String */
print #ExecSQL
print #ParameterDefinition
print #Required_Period
print #KPI_Value
EXECUTE sp_executesql #ExecSQL, #ParameterDefinition, #Required_Period, 'Result', #KPI_Value Output
END
Fetch Next from KPI_Cursor into #StoredProcedure, #Periodic
END
Close KPI_Cursor
Deallocate KPI_Cursor
The stored procedures have parameters as follows:
ALTER PROCEDURE [dbo].[sp_KPI_People_Added_Count]
#Period VarChar(5), -- MTD or YTD
#Result_Type VarChar(10), -- Summary, Result or Detail
#Result Decimal(14,4) OUTPUT -- The returned result
AS
....
The output is as follows:
Prod.dbo.sp_KPI_People_Added_Count
#Period VarChar(5), #Result_Type VarChar(10), #Result Decimal(14,4) OUTPUT
MTD
0.0000
Msg 201, Level 16, State 4, Procedure sp_KPI_Cust_Added_Count, Line 0
Procedure or function 'sp_KPI_People_Added_Count' expects parameter '#Period', which was not supplied.
An alternative way...
EXEC has the little used form EXEC #module_name_var
So you can do this
If #Periodic = 'Z' BEGIN
SET #module_name_var = N'Prod.dbo.' + #StoredProcedure;
EXEC #module_name_var #Required_Period, 'Result', #KPI_Value Output
END
One observation about your original code...
Use N'Result' for the 2nd parameter. sp_executesql says (my bold)
[ #param1= ] 'value1'
Is a value for the first parameter that is defined in the parameter string. The value can be a Unicode constant or a Unicode variable. There must be a parameter value supplied for every parameter included in stmt.