Is there a way to pass temporary tables across the stored procedures - sql

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.

Related

Reduce duplication of creation of SQL temp tables

I have multiple (more than 12) SQL Stored Procedures that setup the same set of temp tables at the start of each procedure. When one of these tables needs modified I need to go make a change in each of those Stored Procedures to match. The temp tables are expected to exist by other stored procedures later in the process. I have no ability to change the process or the flow of these stored procedures or the fact of using these as temp tables, I am coming at it from a DRY approach and looking for a way to consolidate the creation of these shared temp tables into a reusable piece of code so that when changes are needed I can do it in 1 file and reduce the amount of duplication happening today.
Example of the stored procedure
CREATE OR ALTER PROCEDURE [dbo].[procedureName]
#inputs ...
AS
BEGIN
DROP TABLE IF EXISTS #Table1
CREATE TABLE #Table1 (...)
DROP TABLE IF EXISTS #Table2
CREATE TABLE #Table2 (...)
...
DROP TABLE IF EXISTS #Table10
CREATE TABLE #Table10 (...)
...
INSERT INTO #Table5
SELECT * FROM data
...
END

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

stored procedures and temp tables

I have to create a 10 stored procedure as follows:
In stored procedure # 1 I create temp table 1 and this temp table is used in stored procedure 2 to create another temp table and this new tem table is used in another STORED PROCEDURE and so on.
I am not sure how to create these stored procedure, because for these stored procedure I need to have temporary tables present in temdb.
Any help
Can you user Global Temporary Tables?
SELECT * INTO ##Users FROM UserTable
The Global temp tables will remain in tempdb until deleted and can be used across different stored procs.
Assuming you want to name the table (or some of its columns) that's about to be created based on the data present in the temp table, you might want to resort to dynamic SQL, since you can't use variables like this:
declare #foo varchar(50)
select #foo = tableName from #tempTable
create table #foo (fooColumn int)
But before you even think of using dynamic SQL, you've got to ask yourself whether you really need this solution.

Why does Microsoft SQL Server check columns but not tables in stored procs?

Microsoft SQL Server seems to check column name validity, but not table name validity when defining stored procedures. If it detects that a referenced table name exists currently, it validates the column names in a statement against the columns in that table. So, for example, this will run OK:
CREATE PROCEDURE [dbo].[MyProcedure]
AS
BEGIN
SELECT
Col1, Col2, Col3
FROM
NonExistentTable
END
GO
... as will this:
CREATE PROCEDURE [dbo].[MyProcedure]
AS
BEGIN
SELECT
ExistentCol1, ExistentCol2, ExistentCol3
FROM
ExistentTable
END
GO
... but this fails, with 'Invalid column name':
CREATE PROCEDURE [dbo].[MyProcedure]
AS
BEGIN
SELECT
NonExistentCol1, NonExistentCol2, NonExistentCol3
FROM
ExistentTable
END
GO
Why does SQL Server check columns, but not tables, for existence? Surely it's inconsistent; it should do both, or neither. It's useful for us to be able to define SPs which may refer to tables AND/OR columns which don't exist in the schema yet, so is there a way to turn off SQL Server's checking of column existence in tables which currently exist?
This is called deferred name resolution.
There is no way of turning it off. You can use dynamic SQL or (a nasty hack!) add a reference to a non existent table so that compilation of that statement is deferred.
CREATE PROCEDURE [dbo].[MyProcedure]
AS
BEGIN
CREATE TABLE #Dummy (c int)
SELECT
NonExistantCol1, NonExistantCol2, NonExistantCol3
FROM
ExistantTable
WHERE NOT EXISTS(SELECT * FROM #Dummy)
DROP TABLE #Dummy
END
GO
This article in MSDN should answer your question.
From the article:
When a stored procedure is executed for the first time, the query
processor reads the text of the stored procedure from the
sys.sql_modules catalog view and checks that the names of the objects
used by the procedure are present. This process is called deferred
name resolution because table objects referenced by the stored
procedure need not exist when the stored procedure is created, but
only when it is executed.

Using Stored Procedure into Select (T-SQL)

I need to access the result of a stored procedure within a select statement, i.e.:
SELECT * FROM [dbo].[sp_sample]
in SQL_Server 2005.
This isn't possible. You would have to create a temporary table to store the results.
Create Table #tmp
(
...
)
Insert into #tmp
Exec dbo.StoredProcedure
The table structure must match the output of the Stored Procedure.
#Barry is right you need to create a temp table and insert into it first, then join that table in your select.
However, there are numerous ways for sharing data between stored procedures, see this excellent article: How to Share Data Between Stored Procedures by Erland Sommarskog
One method that may work for you is to "share" a temp table. The #temp table is created in the Parent procedure and can be used by the Child: http://www.sommarskog.se/share_data.html#temptables