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
Related
I want to write a stored procedure to loop through set of records and for each of the record execute another stored procedure.
Select query returning list of id's:
select id
from abc
where some condition
I have a stored procedure usp_get_data #id=id which I want to execute for each of the rows of the select query. I do not want to use cursor. What are the other ways I can achieve this?
foreach(item in select statement)
{
execute stored procedure
}
The sub stored procedure will return a list of records which I will then return back from the main stored procedure
I do not want to use cursor. What are the other ways I can achieve this?
Rewirte the stored procedure to operate over a set of data. You can pass bulk data to a stored procedure using a table-valued parameter, or by loading data into a Temp table, which the stored procedure then uses.
Or use a cursor. They aren't the worst thing, and "calling a stored procedure for each row" is probably the most common legitimate use of a cursor. Also the looping-without-a-cursor solutions are all dumb and worse than using a cursor.
I have 4 stored procedures. I need to take the result of the first stored procedure (2 temp tables) and pass it into the second stored procedure. These temp tables need to be used in the from clause in the second stored procedure.
Similarity the third and fourth stored procedures need results from the previous stored procedures.
is there a way to pass temporary tables across the stored procedures?
Regarding this comment, "it was 1 Sp but we broke it into 4 so its easier to alter if needed", I suggest that you break it up even more. In other words, implement encapsulation.
Have a separate stored procedure for each time you want to select data from the actual tables. Do not populate temp tables in these procedures, just return the data.
Then write a stored procedure that creates and populates temp tables from the procs mentioned above, and does the necessary processing.
Here is a simple example:
create procedure GetData1
select Field1, Field2
from blah, blah, blah
create procedure AssembleAllData
create table #temp1 (Field1, Field2)
insert into #temp1
exec GetData1
select Field1, Field2, etc
from #temp1 join anActualTable etc
drop table #temp1
In your current SP1, you can create temporary table pass the name to the second stored procedure like below
SP1 code
IF OBJECT_ID('tempdb.dbo.#TempTable1') IS NOT NULL
DROP TABLE #TempTable1
EXEC SP2 N'#TempTable1'
Inside the SP2 you can insert the values into #TempTable1 which will be available to the calling SP
SP2 code
CREATE procedure [dbo].[SP2]
#outTempTable NVARCHAR(128)
AS
IF #outTempTable IS NOT NULL AND LEN(#outTempTable) > 0
BEGIN
EXEC ( 'INSERT INTO ' + #outTempTable + ' SELECT * FROM TableA' )
END
Your question sounds more like an answer than a question. Just do as you described.
You don't need to pass the data in the temp tables from one procedure to the next. The data is just there. In one procedure you write to the temp table and in the next procedure you read from the temp table.
I would also not create temp tables dynamically, just create them and let them wait for data. This assumes that the temp table data is local to a session (in oracle this is the case and in a way the reason why temp tables exist).
Also I would opt against passing table names between procedures. There is almost always a better way and it is a no-no anyways. If you are under the impression that you need variable temp table names, then you really want to add another column to the temp tables (you may even call it "temp_table_name", though it almost certainly means something different). Then you can pass the "temp_table_name" around and the selects would need a where temp_table_name = ... and the inserts would have to populate this extra column.
I am trying to use a stored procedure that contains two different cursors as table input like such:
INSERT INTO table1 EXEC * FROM tblDailySales
The stored proc contains two cursors - I did not run just using.
I get the following error:
A cursor with the name 'csrDistricts' does not exist.
I also, get this error
An INSERT EXEC statement cannot be nested
The stored proc contains no EXEC that I can see.
What kind of stored proc other than simple SELECT can be used as source for table?
Is table1 already defined? If so all you should have to do is
INSERT INTO table1
EXEC storedProcedureName
Now, the trick is, the stored procedure will only be able to return one result set and insert into the table.
If you need to insert two different result sets, you'll have to gather then in two different stored procedures, then run two INSERT statements.
If you must do them at once, you'll need to do the insert from within the stored procedure.
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.
One Stored procedure returning multiple result sets and I need only the last result set, How do I achieve this without changing original procedure. am using the last reulst set in further processing in other Stored procedure.
if you are "filling" a dataset in c#, very simple, just use:
datasetobj.Tables[datasetobj.Tables.Count-1].Table
to get the DataTable
if doing this within sql procedures (i.e. one procedure calling another that returns multiple), best solution would be to use output variables. concept:
procedure1 returns multiple resultsets
when calling:
declare #table1 table (), #table2 table ()
exec procedure1 out #table1, out #table2