Calling a stored procedure from another stored procedure - sql

I have two fairly large and complex stored procedures. I want to call a second stored procedure from the first stored procedure. For example:
-- stored_procedure_one
select tb1.col1, tb1.col2, sp1.col3, sp1.col4
from table1 tb1
inner join stored_procedure_two sp1 on sp1.col1 = tbl1.col1
Is something similar possible with SQL as the above script gives me an invalid object error message.
Using a temp table is not good in this example, because if I did that, it would take an hour just to fill the temp table with all the data from the second stored procedure. I only want the stored procedure to return the needed data.

This is not going to work. You cannot join on a stored procedure. However, you could consider changing stored_procedure_two into a table-valued user defined function. You could then 'join' via a Cross Apply. I have done this on numerous occasions and it works quite well.
If the second stored procedure is too large and complex, it may not be possible to convert to a UDF. In this case, I think your only alternative is to save the results of the second stored proc to a table and join on that. But that could be somewhat inefficient and messy.

You may add the results of the second procedure in a local variable table
DECLARE #Table TABLE
(
Col1 int,
Col2 ...
)
INSERT INTO #Table
EXEC stored_procedure_two
select tb1.col1, tb1.col2, sp1.col3, sp1.col4
from table1 tb1
inner join #Table tbl2 on sp1.col1 = tbl1.col1

Related

Postgresql Procedure select into temp table

Being a recent convert from SQL Server, I am getting to know Postgresql a bit.
I really hate having to write nested selevt statements in SQL since I find that the readability and maintainability of the code suffers when I do.
Usually I would create a stored procedure in SQL Server where I would select something into a temporary table, that I can then use in another select statement.
CREATE OR ALTER PROCEDURE Procname
AS
BEGIN
SELECT
Somewhere.Col_1,
Somewhere.Col_2
INTO
#Temptable
FROM
Somewhere Somewhere
SELECT
Temptable.Col_1,
Somewhere_Else.Col3
FROM
#Temptable Temptable
INNER JOIN
Somewhere_Else.Col_2 = Temptable.Col_2
END
When I execute this procedure I would get returned the final select query
How would I replicate this procedure in Postgresql?
I know that you can select into a temporary table, but I cannot seem to figure out how to use this table in the next select statement within the same procedure
Create a set returning function, there is no need for a temp table at all.
CREATE function Procname()
returns table(col_1 ???, col2 ???) --<< change data types here
AS
$$
SELECT
Temptable.Col_1,
Somewhere_Else.Col3
FROM Somewhere Temptable
INNER JOIN Somewhere_Else ON Somewhere_Else.Col_2 = Temptable.Col_2;
$$
language sql
stable;
But for such a simple statement, I would rather create a view.

Calling Stored procedure with cross apply from another stored procedure gives error SQL server

I have been trying to call stored procedure from another stored procedure. Now issue is that under lying nested stored procedure contains CROSS APPLY with temp table and it runs fine when i execute it directly.
But when i try to call this SP from other SP, it gives error that one of the column is invalid. "Invalid column name 'levels'" in this case.
Plus, when i execute this SP from calling SP SQL window with passing parameters, it runs fine and whole main procedure starts running smoothly.
I am not able to get why this issue happens. Below is kind of implementation for reference.
1.) Main SP
CREATE STORED PROCEDURE ....
INSERT INTO #TempTable
EXEC [Child_SP] #Param1 = 1, #Param2 = 1
...
Gives error.
2.) Once i execute below given as single statement once from main PS. It starts working fine.
EXEC [Child_SP] #Param1 = 1, #Param2 = 1
3.) Child SP has CROSS APLLY with one of the temp table. something like below.
SELECT ID, '1,2,3,4,5' AS levels
INTO #Temp1
FROM ABC
SELECT ID
FROM #Temp1 x0
CROSS APPLY (SELECT * FROM dbo.iter_charlist_to_table(x0.levels, ',') AS x) x1
WHERE x1.listPos > 1
"iter_charlist_to_table" is table value function which get values as table from comma seperated list.
Is it related to SQL Thread anyhow or whats the issue? Thanks.
I recommend to use this code to drop your tmp table on the beginning of the SP because your insert INTO will ALWAYS tried to create the table doesn't matter if already exists.
IF OBJECT_ID('tempdb..#Temp1') IS NOT NULL DROP TABLE #Temp1
If you share more code will be more helpful to understand.
And just in case don't forget to put the alias on the table maybe this correction sometimes is not needed but is a good practice for avoid problems on querying the data on joined tables
SELECT x0.ID
FROM #Temp1 x0
CROSS APPLY (SELECT fnAlias.* FROM dbo.iter_charlist_to_table(x0.levels, ',') fnAlias) x1
WHERE x1.listPos > 1

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

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.

How do I grab multiple outputs from a stored procedure into temp table

My stored procedure returns me two outputs. I want to use one of them in another stored procedure. So trying to grab the second output in a temp table. but since the structure of both the outputs are different, there fore I always get "Column name or number of supplied values does not match table definition."
Even if I change the order of the output(first output second and second output first), it is not working.
I am establishing a brand new application and I need to use the stored procedure again an d again in another stored procedures. If I face this type of situation, probably I need to rewrite lot of code.
There is a very nice questions, but this covers only one output.
Insert results of a stored procedure into a temporary table
thanks
You can't, not without modifying the stored procedure.
In SQL Server, you can only insert the first result set of a stored procedure into another table, via INSERT...EXEC. Column count and positions must match exactly, and INSERT...EXEC cannot be nested, ie you cannot insert from proc1 into a table in proc2, and then insert from proc2 into a table in proc3. So INSERT...EXEC is an altogether unsatisfying solution.
The workaround is modify the procedure to insert results into temporary tables defined in the calling scope, eg:
create proc get_some_data as
insert #temp1 (col1, col2) select col1, col2 from table1
insert #temp2 (colA, colB) select colA, colB from table2
go
create table #temp1 (col1 int, col2 int)
create table #temp2 (colA int, colB int)
exec get_some_data
select * from #temp1
select * from #temp2
drop table #temp1
drop table #temp2
go
If you can't modify the procedure, you are out of luck. CORRECTION: as HABO kindly pointed out, you could use the CLR to iterate the result sets. See link below for details. Not too bad if you know what you are doing, and have no other choice.
For more details on sharing data between stored procedures, see this very comprehensive article by Erland Sommarskog: http://www.sommarskog.se/share_data.html

Combine stored procedure and query in T-SQL

How do I combine executing of a stored procedure and using its result or parameters in a regular SQL query?
For example I would like to do something like the following:
-- passing result of SELECT to SP
SELECT a, b FROM t
EXEC my_sp a, b
-- passing result of SP to INSERT
INSERT INTO t
EXEC my_sp a, b
etc.
no, you need to use a temp table
create table #results (col1 int, col2 varchar(5) ...)
INSERT INTO #results
EXEC YourProcedure #parma...
then you can join to it
SELECT
*
FROM YourTable y
JOIN #results r ON ...
....
if you don't know the columns and data types from the procedure you can use this excellent answer: Insert results of a stored procedure into a temporary table
In brief it uses OPENROWSET to execute the stored procedure into a #temp table that is created on the fly, without the need to name and know the type all the columns.
If your SP can be rewritten as an inline table valued UDF, these typically perform very well and are equivalent to a parametrized view. ITVF can be used any place you would use a table or view.
If your SP won't work as an inline TVF (local variable manipulation required), it may work as a multi-statement TVF (contains a BEGIN/END) which may or may not perform poorly depending on what you have to do.
After your SP has been turned into a UDF, you can then still call the UDF from your SP (SELECT* FROM udf(params)) or elsewhere it can be used for joins, etc, so all your code is inside the UDF - no duplication.