TSQL: Call a stored procedure from another stored procedure and read the result - sql

I have a stored procedure that, ending with a SELECT, returns a recordset. I can call it within anoher stored procedure like this:
EXEC procedure #param
How to get the returning recordset? Thanks

You can create a temp table and then use INSERT INTO #MyTable EXEC procedure #param.
There are some other techniques listed here.

AFAIK, you can't. What you probably want to do is use a function for your first (or both) procedures. Functions can only return one thing, but they can return a table. Stored procedures can return multiple results, but not to other functions/stored procedures.
e.g.:
CREATE FUNCTION [dbo].[fn_GetSubordinates] (
#sPersonID VARCHAR(10),
#nLevels INT
)
RETURNS #tblSubordinates TABLE
(
Person_Id VARCHAR(10),
Surname char(25),
Firstname char(25)
)
AS
BEGIN
...

If you are using SQL Server 2008, I would recommend returning a Table-Valued Parameter.
http://msdn.microsoft.com/en-us/library/bb510489.aspx

You can do this with an output variable in the stored proc. For example:
CREATE PROCEDURE sp_HelloWorld #MyReturnValue int OUT
AS
SELECT #MyReturnValue = 100
Return #MyReturnValue
To call this stored proc, do the following:
DECLARE #TestReturnVal int
EXEC sp_HelloWorld #TestReturnVal output
SELECT #TestReturnVal

First, you CANNOT RETURN a recordset by stored procedure. By return, a stored procedure can only return integers.
You mentioned SELECT statement, which is a DQL and just for display purpose.
The way you can do to work around this issue is that you can assign the recordset to a global temporary table which can also be accessed within the outer stored procedure.

Related

Convert Query to Stored Procedure

In db2, can someone show me how to convert a query into a stored procedure, so that when the stored procedure is called it simply returns the same result set as the query would return.
For example, let say I have query like this:
select * from tablename
How would you turn this into a stored procedure that returns the same record set as is returned by just simply running the query directly?
Just create a procedure
Format is as follows
CREATE PROCEDURE <<SPmyProcedure>>
AS
BEGIN
<---procedure definition here--->
select * from tablename
END
Then you can just call the procedure name and it will perform your query.
via
exec SPmyProcedure
Why you dont use table valued function like this?
ALTER FUNCTION [db].[fn_tablename]
(
)
RETURNS TABLE
AS
RETURN
(
SELECT * from [db].tablename
)

Execute a stored procedure from within another stored procedure's SELECT statement?

I would like to execute a stored procedure X from within the SELECT statement of stored procedure Y, so that X's value can be returned as part of Y's data.
I am trying the following syntax, but it's apparently not valid.
SELECT name, type, (EXEC X #type=type)
FROM table
As I hope you can see above, I need to pass the current row's type value to procedure X to get the proper return value.
Disclaimer: I probably just don't know what I'm doing.
The approach what you have tried is invalid. Instead of the X as the stored procedure convert it as user-defined function. like the below
Create function dbo.fnGetTypeDetail
(
#type varchar(50)
)
returns varchar(100)
As
Begin
return --do your operation;
End
And replace your query as:
SELECT name, type, dbo.fnGetTypeDetail(type) AS TypeDetail
FROM table
For sample, I created a scalar function. Based on your requirement you can create inline table valued function as per the example
You can't EXEC a stored proc inside a SELECT statement.
What you can do is INSERT..EXEC a stored proc into a temp table, and then run a SELECT statement that queries that temp table, while joining to other tables if desired.
Psuedo-example:
INSERT INTO #Tmp (Column1) EXEC X;
SELECT Name, Type, (SELECT Column1 FROM #tmp)
FROM MyTable

Is it possible to retrieve Selected Columns from Stored Procedure?

I have a stored procedure which returns a few columns from a SELECT. Now I need to grab 2 columns out of those columns in my new stored procedure and use them.. I am trying to do this using EXEC method. Is it possible to do this?
Ex : Original stored procedure:
CREATE PROCEDURE myBaseProcedure
#stId INT
AS
BEGIN
SELECT Name,
Address,
StudentId,
Grade
FROM Student
WHERE StudentId = #stId
END
New stored procedure:
CREATE PROCEDURE myNextProcedure
BEGIN
EXEC myBaseProcedure 19 -- Here I need to grab only StudentId and Name??
END
Given that you cannot dump to a temp table or table variable since the base stored procedure might sometimes add columns, there are three approaches that would do this:
You can effectively SELECT from a stored procedure using either OPENROWSET or OPENQUERY
You can use SQLCLR to create a table-valued function that executes the procedure, returns a struct of just the fields that you want, which will be the only fields that you read or "get" from the SqlDataReader.
You can use SQLCLR to create a stored procedure that executes the procedure to get a SqlDataReader, and instead of returning the SqlDataReader to SqlContext.Pipe.Send(), you would use SendResultsStart, SendResultsRow, and SendResultsEnd. You would create a SqlDataRecord of just the fields you wanted, and those would also be the only fields that you read or "get" from the SqlDataReader. While this still leaves you with a stored procedure, the filtering of the fields is done within the CLR-based proc so the output is guaranteed to be just the fields you want, regardless of how the result set structure of the base stored procedure changes. In this way you could create a local temp table to dump the results to, which would be better for JOINing to other tables. This method also allows for you to pass in a list of fields to the CLR-based stored procedure that would be parsed and used as the fields to dynamically construct the SqlDataRecord with as well as to dynamically determine which fields to get from the SqlDataReader. That would be a little more complicated but also quite a bit more flexible :).
You don't need to create a new stored procedure for this, you can integrate the stored proc call in a simple query using OpenQuery or use a temporary table.
Using OPENQUERY
SELECT Name,
Address
FROM OPENQUERY(ServerName, 'EXEC myBaseProcedure 19')
-- WHERE your_field = expected_value --> if you need to add filters
Using Temp table
Declare #MyTempTable Table (columns definitions)
Insert #MyTempTable Exec myBaseProcedure 19
Select Name,
Address
FROM #MyTempTable

Insert SQL stored procedure values into another stored procedure

I have a large stored procedure that returns a record for a person, there are four fields that I need to return very specific values for. I have another stored procedure that performs this specific action.
The small stored procedure is as follows:
SELECT TOP 1
wea.field,
wea.degree,
wea.degreeyear,
wpp.ProgramCategory
FROM dbo.webeventaffiliation wea
LEFT JOIN dbo.WebProgramParticipants wpp
ON
wea.userid = wpp.UserID AND
wea.eventid = wpp.eventid
INNER JOIN dbo.WebProgramCategoryDescriptions wpcd
ON
wpcd.ProgramCategory = wpp.ProgramCategory
WHERE wea.UserID = #UserID
ORDER BY wea.datelastmodified DESC
LARGE STORED PROCEDURE SAMPLE RETURN DATA:
Name: XXXXX
Address: XXXXX
Field: [small stored procedure value]
Degree: [small stored procedure value]
DegreeYear: [small stored procedure value]
ProgramCategory: [small stored procedure value]
My question is how do I get the 4 data items from this stored procedure into their respective columns within the dataset that is returned from the large stored procedure?
Using a table-valued function instead of a stored procedure could be helpful. You will be able to use the TVF just like a table ie:
SELECT
COLUMNS_NAMES
FROM
TVF(PARAMS)
As your small stored procedure doesn't write anything, you could just write it as a table valued function.
You can then apply the function to an entire data-set by using APPLY.
(Table valued functions that are written INLINE (not multi-statement) are then explanded macro-like to execute extremely efficiently. This is perfect for your description as the function would just be a single SELECT statement already.)
The Function:
CREATE FUNCTION dbo.your_function(#user_id AS INT)
RETURNS TABLE
AS
RETURN
<your query>
The function used in a query inside your big SP:
SELECT
...,
user_detail.field,
user_detail.degree,
user_detail.degreeyear,
user_detail.programcategory
FROM
...
CROSS APPLY
dbo.your_function(some_table.user_id) AS user_detail
In general I use functions to encapsulate queries, and only wrap them up in Stored Procedures if...
1) I need to write data. (Functions can't INSERT, UPDATE or DELETE)
2) I want to create an API like interface to client applications.
Since you're getting only one row with four values you could use OUTPUT parameters:
EXECUTE SomeSmallerProcedure
#field OUTPUT, #degree OUTPUT, #degreeyear OUTPUT, #ProgramCategory OUTPUT;
Your procedure listed above would change to:
ALTER PROCEDURE SomeSmallerProcedure
#field varchar(255) OUTPUT,
#degree varchar(255) OUTPUT,
#degreeyear varchar(255) OUTPUT,
#ProgramCategory varchar(255) OUTPUT
AS BEGIN SET NOCOUNT ON;
SELECT TOP 1
#field = wea.field,
#degree = wea.degree,
#degreeyear = wea.degreeyear,
#ProgramCategory = wpp.ProgramCategory
-- ... rest as before
The signature of your procedure above would have to include those parameters explicitly for OUTPUT.

Use Stored procedure like a function

I need to deal with the table name as a variable.Then I must using dynamic sql and therefore I must using Stored procedure.
But the problem that how can I use the stored procedure like a custom sql function.
e.g: select col1,(Exec sp1 param1,'tbName') from table1
Finally,I changed my design and and use dynamic SQL in one upper level.
This will be posible in sql server denali that introduces the new keywords "WITH RESULTSET".
The alternative on current sql versions is passing a temp-table to the stored procedure
Stored procedures can return scalar values through output parameters. Here's an example (from here).
Create the stored procedure like this:
CREATE PROCEDURE _4P_test
#intInput INT,
#intOutput INT OUTPUT
AS
SET #intOutput = #intInput + 1
Call it like this:
DECLARE #intResult INT
EXEC _4P_test 3, #intResult OUT
SELECT #intResult
However you should try to design your system so that you don't have to use dynamic SQL in the way you described.