Receive multiple result sets in stored procedure - sql

I have a procedure Sp1:
Begin
select product_id, product_name
from product
select dept_id, dept_name
from department
end
My procedure returns two result sets, now I call to this procedure in another procedure using:
exec SP1
How can I access the results of SP1 in this other procedure?

You can get the results from an SP into a table by using the INSERT INTO..EXEC syntax. I don't advise it, however, as it relies on all datasets being returned from the SP to have the same definition:
USE Sandbox;
GO
CREATE PROC TestProc1 AS
SELECT *
FROM (VALUES(1,'T-Shirt'),
(2,'Jeans'),
(3,'Spotlight')) V(ProductID,ProductName);
SELECT *
FROM (VALUES(1,'Clothing'),
(2,'Lighting')) V(DeptID, DepartmentName);
GO
CREATE TABLE #TempTable (ID int, [Name] varchar(15));
INSERT INTO #TempTable
EXEC TestProc1;
SELECT *
FROM #TempTable;
GO
DROP TABLE #TempTable
DROP PROC TestProc1;
As soon as you throw in a dataset that has a different definition (for example, different number of columns, or perhaps a value that can't be implicitly cast (i.e. 'abc' to an int) it'll fail. For example:
USE Sandbox;
GO
CREATE PROC TestProc1 AS
SELECT *
FROM (VALUES(1,'T-Shirt',1),
(2,'Jeans',1),
(3,'Spotlight',2)) V(ProductID,ProductName,DeptID);
SELECT *
FROM (VALUES(1,'Clothing'),
(2,'Lighting')) V(DeptID, DepartmentName);
GO
CREATE TABLE #TempTable (ID int, [Name] varchar(15));
--fails
INSERT INTO #TempTable
EXEC TestProc1;
SELECT *
FROM #TempTable;
GO
DROP TABLE #TempTable;
GO
CREATE TABLE #TempTable (ID int, [Name] varchar(15),OtherID int);
--fails
INSERT INTO #TempTable
EXEC TestProc1;
SELECT *
FROM #TempTable;
GO
DROP TABLE #TempTable
DROP PROC TestProc1;
You should really be using multiple SP's and handling the data that way.

Related

Why do I get an invalid column name error when using a temp table twice?

If I run each of these batches separately, it works. However, if they are combined into one script (like what is done when a DACPAC script runs, or putting them both into one tab in SSMS), I get an Invalid column name error on the second insert. Why is that? If I need these to run in one script, do I need to use a different name for the temp table for the second batch? Or am I missing something that would allow me to use the same name?
IF OBJECT_ID('tempdb..#source') IS NOT NULL DROP TABLE #source
SELECT FirstName, LastName INTO #source FROM Musician WHERE 1 = 0; -- set up temp table schema
INSERT INTO #source ( FirstName, LastName )
VALUES
('Geddy', 'Lee'),
('Alex', 'Lifeson')
SELECT * FROM #source
GO
IF OBJECT_ID('tempdb..#source') IS NOT NULL DROP TABLE #source
SELECT [Name], Genre INTO #source FROM Band WHERE 1 = 0; -- set up temp table schema
INSERT INTO #source ( [Name], Genre )
VALUES
('Rush', 'Rock'),
('Ratt', 'Rock')
SELECT * FROM #source
GO
Each batch is parsed independently. So it works when you use GO because they are in different batches.
When you put everything in the same batch, SQL Server parses what it sees, and it is blind to logic like DROP commands hidden behind IF conditionals. Try the following and you'll find the same:
IF (1=0) DROP TABLE IF EXISTS #x; CREATE TABLE #x(i int);
IF (1=1) DROP TABLE IF EXISTS #x; CREATE TABLE #x(j date);
You and I both know that only one of those will ever execute, but the parser spots the redundant table name before it ever gets to execution (or evaluating any conditionals).
This works because, again, each batch is now parsed in isolation:
IF (1=0) DROP TABLE IF EXISTS #x; CREATE TABLE #x(i int);
GO
IF (1=1) DROP TABLE IF EXISTS #x; CREATE TABLE #x(j date);
This will in fact fail even though it passes parsing (highlight and select Parse instead of Execute), so the blindness goes both ways:
IF (1=0) DROP TABLE IF EXISTS #x; CREATE TABLE #x(i int);
GO
IF (1=1) CREATE TABLE #x(j date);
Using go after dropping the tables in both block will do the trick.
IF OBJECT_ID('tempdb..#source') IS NOT NULL DROP TABLE #source
go
SELECT FirstName, LastName INTO #source FROM Musician WHERE 1 = 0; -- set up temp table schema
INSERT INTO #source ( FirstName, LastName )
VALUES
('Geddy', 'Lee'),
('Alex', 'Lifeson')
SELECT * FROM #source
GO
IF OBJECT_ID('tempdb..#source') IS NOT NULL DROP TABLE #source
go
SELECT [Name], Genre INTO #source FROM Band WHERE 1 = 0; -- set up temp table schema
INSERT INTO #source ( [Name], Genre )
VALUES
('Rush', 'Rock'),
('Ratt', 'Rock')
SELECT * FROM #source
GO

How to capture Output of SQL queries and

I have a Database and i want to execute few queries on it, and the results of the queries i.e. message, has to be comapared in my code if it is expected or not.
Please let me know how to capture the output of the SQL queries in any variable that can be used later in code for comparision.
Try the following Method :
Create a Table with the Same structure as of your Procedure output
Insert the Result of the SP Execution to the Table
Compare your Query result with the Table
Like this
CREATE PROCEDURE dbo.uSp_Temp
AS
SELECT
GETDATE() "MyDate"
DECLARE #T TABLE
(
MyDate DATE
)
INSERT INTO #T
EXEC uSp_Temp
SELECT
*
FROM #T
You can use Temp tables or temp variable to save the result set of a query.
Below is the sample for temp table
create table #temp (id int)
insert into #temp
select 1 as id
select * from #temp
Below is sample for Temp variable
declare #temp table (id int)
insert into #temp
select 1 as id
select * from #temp

How to get one data table from Stored procedure that has multiple select statements using sql server

I have two select statements in my stored procedure:
alter proc multiple
select * from table-one
select * from table-two
Now how to get the data of table-one only by executing the stored procedure?
You can pass input variable and use if statment. For example:
ALTER PROCEDURE multiple
#choice INT
AS
BEGIN
IF (#choice = 1)
BEGIN
SELECT * FROM Table1
END
IF (#choice = 2)
BEGIN
SELECT * FROM Table2
END
IF (#choice = 3)
BEGIN
SELECT * FROM Table1
SELECT * FROM Table2
END
END
And execution of procedure:
EXECUTE multiple #choice = 1 -- to use 1st select
EXECUTE multiple #choice = 2 -- to use 2st select
EXECUTE multiple #choice = 3 -- to use both selects
You can use TEMP table to fill all result in the temp table.
if you have 3 table name tab_1,tab_2,tab_3 then create a temp table with column maximum from these table(tab_1,tab_2,tab_3) and add a extra column to temp table to identify data from tables.
tab_1(id bigint,name varchar(50))
tab_2(id bigint,email varchar(50))
tab_3(id bigint,address varchar(50),phone varchar(50))
then your temp table should be like this
#tmp(col1 bigint(),col2 varchar(50),col3 varchar(50),from_table varchar(50))
e.g
create table tab_1
(
id bigint identity(1,1),
name varchar(50),
email varchar(50)
)
insert into tab_1(name,email) values
('a','a#mail.com'), ('b','c#mail.com'),
('a1','a1#mail.com'), ('a2','a2#mail.com'),
('a3','a3#mail.com'), ('a4','a4#mail.com'),
('b1','b1#mail.com'),('b2','b2#mail.com')
create table tab_2
(
id bigint identity(1,1),
name varchar(50),
email varchar(50),
amount decimal(18,2)
)
insert into tab_2(name,email,amount) values
('a','a#mail.com',12.5), ('b','c#mail.com',11.6),
('a1','a1#mail.com',11.7), ('a2','a2#mail.com',88.9),
('a3','a3#mail.com',90), ('a4','a4#mail.com',45),
('b1','b1#mail.com',78),('b2','b2#mail.com',88)
and the Sp should be like
create table #tab(col1 bigint,
col2 varchar(50),
col3 varchar(50),col4 varchar(50),table_from varchar(50))
insert into #tab(col1,col2,col3,table_from)
select id,name,email,'table_1' from tab_1
insert into #tab(col1,col2,col3,col4,table_from)
select id,name,email,amount,'table_2' from tab_2
select * from #tab
FIDDLE DEMO

Inserting into table the values returned from stored procedure

I have a procedure which has a select statement as below:
CREATE PROCEDURE pr_test
as
SELECT * from SOURCETABLE
Can I insert into a temp table by executing the stored procedure pr_test by any chance?
You can use INSERT EXEC
declare #t results (field1 int, ....)
insert #t (field1,...)
exec pr_test
CREATE PROCEDURE pr_test
as
begin
CREATE TABLE #TibetanYaks(
YakID int,
YakName char(30) )
INSERT INTO #TibetanYaks (YakID, YakName)
SELECT YakID, YakName
FROM dbo.Yaks
WHERE YakType = 'Tibetan'
-- Do some stuff with the table
drop table #TibetanYaks
end

How can I create two temporary tables with the same structure without write twice?

How can I create two temporary tables with the same structure without write twice?
Something like that:
DECLARE #TEST_TABLE1, #TEST_TABLE2 TABLE
(
FIELD1 INT,
FIELD2 INT
)
and NO:
DECLARE #TEST_TABLE1 TABLE
(
FIELD1 INT,
FIELD2 INT
)
DECLARE #TEST_TABLE2 TABLE
(
FIELD1 INT,
FIELD2 INT
)
These are not "temp tables", a temp table is CREATE TABLE #TempTable(x int)
to make this work for true table tables, try:
CREATE TABLE #TempTable(x int)
insert into #TempTable values(5) --test data to show no data copied to new table
select * into #tempTable2 from #TempTable where 1=2
select * from #TempTable
select * from #TempTable2
These are table vaiables (#tableVariable) and you have to declare each variable, there is no way around it.
The only very non-standard way I can think this may work is to just write to the sys.tables directly, but you would still have to do two inserts, but you are doing the tables at the same time.
That may not be what you want, but short of using a stored procedure, and making one call from your app, and two on the database I can't think of any other solution.
Create the first temp table, then select into a second temp table:
-- Create first temp table
CREATE TABLE #TEST_TABLE1
(
FIELD1 int
,FIELD2 int
)
-- Select into second temp table
SELECT *
INTO #TEST_TABLE2
FROM #TEST_TABLE1
-- Vet existence of both temp tables
SELECT * FROM #TEST_TABLE1
SELECT * FROM #TEST_TABLE2