There is a stored procedure sp and a table variable #tbl
Insert into #tbl
Exec sp
Above works fine initially.
We changed the stored procedure output and added additional output columns. The insert statement above fails with 2nd version of the stored procedure.
The above SQL needs to work with version 1 of sp and version 2 of sp
What can be done?
SQL Server doesn't provide the option to specify the column names while doing the insert from sp output
The only way to do it is to use the EXECUTE WITH RESULT SETS to determine the exact columns to return from the stored procedure. This will give you the option to specify the column names to insert into the table variable from the stored procedure output.
Insert into #tbl(col1, col2, col3) EXECUTE sp
WITH RESULT SETS (
(col1 INT,
col2 INT,
col3 nvarchar(50))
)
For more information, see here.
Related
I wrote a SQL query, it is 300+ line and I made this as a procedure.
I want to run two times this procedure with different parameters and then want to see all result in one table.
For example:
exec sp_xxxxx 4652,'2022-02-07 00:00:00.000',1
// Returns 2 columns, number of rows can vary
exec sp_xxxxx 4652,'2022-02-14 00:00:00.000',1
// Returns 2 columns, number of rows can vary
I run these together, then I hope to get a result of 4 columns
// 4 column,number of rows can vary
I tried openrowset but SQL blocked.
How can I do this, I would be very happy if you can help.
There's not enough information to provide a demonstrable solution, but the approach should be:
Create temp table #T1(col1, col2)
Create temp table #T2(col1, col2)
Insert into #T1(col1, col2) exec proc
Insert into #T2(col1, col2) exec proc
select t1.col1, t1.col2, t2.col1, t2.col2
from #T1 inner/left/full join #T2 on<criteria>
Also note that prefixing procedures with "sp" is not recommended, this is reserved by MS and indicates a Special Procedure. Choose a different prefix - or no prefix.
Start with creating a table type than matches the output of your procedure.
For example:
CREATE TYPE XxxxxTblType AS TABLE(
Col1 varchar(10) not null,
Col2 decimal(8,2) not null
);
This table type could also be used by your procedure.
Then use a variable with that table type to collect the results from the procedures. Then create a temporary table from that table variable.
declare #Xxxxx XxxxxTblType;
insert into #Xxxxx exec sp_xxxxx 4652,'2022-02-07 00:00:00.000',1;
insert into #Xxxxx exec sp_xxxxx 4652,'2022-02-14 00:00:00.000',1;
select * into #tmpXxxxx from #Xxxxx;
Now you can query the temporary table.
select * from #tmpXxxxx;
How can i insert values of a nested stored procedure into a table.
For example if i created a stored procedure like this.
Create procedure New
begin
create table #tmp
(
id int,
name varchar(50)
);
insert into #tmp
exec stored_procedure 1,2;
insert into #tmp
exec stored_procedure 1,2;
select * from #tmp
end
Now if I execute this command, SQL Server will display error:
insert into #table
exec New;
Does anyone have a solution for this problem? Please share
Right now you’re not returning any data from your procedure New. If you want it to return data for your calling code to insert you’ll need a select statement in it.
Eg add a line at the end:
SELECT * FROM #tmp;
Also, you can’t nest INSERT EXEC statements. See this answer for more details
You can't do a insert with de values returned by a Stored Procedure.
In your case the easiest way is to change de stored procedures by table functions.
You can find more about table functions here
My opinion is to make it simple if u can.
I have a stored procedure that returns this result:
The way I call the stored procedure is:
Exec uspGetStandardUsingRoleandPhase '1908003'
I want to store these results into a temp table so I used insert into like this:
IF OBJECT_ID(N'tempdb.dbo.#tmp', N'U') IS NOT NULL
DROP TABLE #tmp
CREATE TABLE #tmp
(
startDate DATE,
endDate DATE,
strPhase NVARCHAR(50),
strBadgeNumber NVARCHAR(30)
)
INSERT INTO #tmp (startDate, endDate, strPhase, strBadgeNumber)
EXEC uspGetStandardUsingRoleandPhase '1908003'
But I get an error like this:
INSERT EXEC failed because the stored procedure altered the schema of the target table.
Hard to say without seeing the code to the stored procedure, but my guess is that the procedure also creates a temp table named #tmp. Try creating a temp table with a different name and running your INSERT EXEC into that, or post the code to the procedure so we can see it.
Worth noting this can also come up in SQL 2016 if you're using Query Store, and it happens to run a clean up during the procedure's execution. They suggest increasing the Query Store size to reduce the likelihood, but other than that, they're not planning to fix it for SQL 2016 (it's fixed in 2017)
https://support.microsoft.com/en-us/help/4465511/error-556-insert-exec-failed-stored-procedure-altered-table-schema
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
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.