I have a temp table in a SP. I insert some values into it. I will need to then EXEC a second SP by sending in the values from the temp table. I would rather avoid having to use local variables.
DECLARE #tmp TABLE
(
Name VARCHAR(200).
Code INT
)
INSERT INTO #tmp
SELECT 'TEST', 100
EXEC MyProc
#Name = --Here I send the values from temp
#Code =
create an actual temp table #TempTable and not a #varibale table, and you can share it between parent and child stored procedures...
http://www.sommarskog.se/share_data.html#temptables
You can't, unless you're on SQL Server 2008 which allows table data types. Which can be used as stored proc parameters.
Otherwise frp SQL 2000/2005, for 10 rows in the temp table, you need loop through 10 inner stored proc calls.
You could wrap it all in a single SP.
Related
I'm trying to run a stored procedure that creates a local table - #table1
The stored procedure is supposed to look for values and create the table and insert the values into it...
INSERT INTO #table1
I execute the stored procedure and it shows that 1 row() affected, however, I am unable to find this table in the list of my tables. Why am I not able to see it or access it?
EDIT: I'm running the stored procedure inside SQL Server against a database. At the end of the stored procedure, the last line is:
Select * from #table1
Thanks.
The #table is a local temp table. It does not exist as a permanent table that you can look for outside the scope of the stored proc. Once the stored proc is run, the temp table is dropped because it is no longer in scope. Temp tables are stored temporarily in the tempdb database but with a different name because two people running the stored procedure at the same time would each have a table that can be referenced in the proc as #table but it would be two separate tables in the tempdb.
Now if what you are doing is looking to see what is in #table at a point in the stored proc in order to troubleshoot the proc, then you need to set thing up in the proc so that you can see the results at different stages or when you hit a certain state such as an error.
This could be something like adding a #debug variable to the proc so that when you are in debug mode, you can select the results to the screen when you are running something like:
CREATE PROC test_proc (#Id INT, #debug BIT = 0)
AS
CREATE TABLE #temp(id INT)
INSERT INTO #temp
VALUES (#Id), (1), (2)
IF #debug = 1
BEGIN
SELECT * FROM #temp
END
UPDATE #temp
SET Id = id-1
IF #debug = 1
BEGIN
SELECT * FROM #temp
END
GO
You would then execute the proc without debugging as so (note that since I am not returning something or inserting to permanent tables, this proc will insert to #temp but you can't see anything. I just didn't want to get complicated here, the steps of the proc will vary depending on what you want to do, the concept I am trying to show is how to use the debug variable):
EXEC test_proc #Id= 5
and with debugging as
EXEC test_proc #Id= 5, #debug= 1
Or it might involved using a table variable instead (because they don't get rolled back on error) and then inserting the data from that table variable into a logging table after the rollback occurs in the Catch block, so that you can see the values at the time the error occurred.
Without knowing more about why you are looking for #temp and what the data means and is used for, it is hard to say what you need to do.
Did you tried refreshing the tables after exceuting Stored procedure
This is running on SQL Server 2008, but the database is in SQL Server 2000 compatibility mode (this I cannot change).
A temporary table is created at the beginning of the stored procedure and then insert into via an EXEC statement from dynamically generated SQL. How is this executing successfully, even though the temporary table (should be, from my understand) is out the execution scope, or does this get bypassed temporarily when performing these statements inside a stored procedure?
Example below:
CREATE PROCEDURE myProc (Param1 int....)
AS
BEGIN
Declare #SQL varchar(max) = null
Create table #tempTable
(
ID int,
Code1 varchar(255),
...
)
SET #SQL = 'insert into #tempTable '
+ ...
EXEC(#SQL)
Select * from #tempTable
END
Any help understanding this would be greatly appreciated!
Thanks!
Shortly:
The temporary table created in the outer batch is accessible inside the dynamic SQL but not vice versa.
See doc
A local temporary table created in a stored procedure is dropped
automatically when the stored procedure is finished. The table can be
referenced by any nested stored procedures executed by the stored
procedure that created the table. The table cannot be referenced by
the process that called the stored procedure that created the table.
What are the best approaches to the below scenario?
In my C# program, I have some sql commands such as UPDATE, INSERT, DELETE. I could execute them in my C# program (which works fine) but I need to execute these sql commands when one of the stored procedure comes to the last line. So I am planning to store the sql commands in some staging table in the same database and then I would like to open this table within the stored procedure and execute one by one.
What is the best approach in terms of opening a table within stored procedure and then traversing through the table based on some condition (like select * from TempStagingTable where customerId = '1000'). If it returns 10 records, I would like to loop them and execute the sql command stored in a column named "CustomSqlScript"
PS: I am using SQL 2008 R2.
Well, you can select the data from table A initially, and instead of using cursor you can use while loop(as it will increase your performance compared to cursor) and then you can execute your predefined SQL statement from table B
Please find below sql scripts to do the same
Please note: I have not made use of any relation,This is just a plain example
CREATE TABLE test1(
customSqlScripts VARCHAR(100)
)
CREATE TABLE test2(
customer_Id INT PRIMARY KEY ,
first_Name VARCHAR(100),
last_name VARCHAR(100)
)
INSERT INTO test1 VALUES('Select first_Name from test2 where customer_Id=')
INSERT INTO test2 VALUES('1','Rohit','Tiwari')
DECLARE #Count INT
DECLARE #iCount INT=0
DECLARE #dummysql VARCHAR(100)
SELECT #Count= Count(*)
FROM test2
WHERE last_name='Tiwari'
WHILE(#icount<#count)
BEGIN
SELECT #dummysql =customSqlScripts
FROM test1
SET #dummysql=#dummysql+'1'
EXEC (#dummysql)
SET #icount=#icount+1
END
I've got a child procedure which returns more than table.
child:
PROCEDURE KevinGetTwoTables
AS BEGIN
SELECT 'ABC' Alpha, '123' Numeric
SELECT 'BBB' Alpha, '123' Numeric1, '555' Numeric2
END
example:
PROCEDURE KevinTesting
AS BEGIN
DECLARE #Table1 TABLE (
Alpha varchar(50),
Numeric1 int
)
DECLARE #Table2 TABLE (
Alpha varchar(50),
Numeric1 int,
Numeric2 int
)
--INSERT INTO #Table1
EXEC KevinGetTwoTables
END
You will not be able to capture both result sets in the parent procedure, like you could with a single one into a temp table. However, there are several other options. Read the excellent article How to Share Data Between Stored Procedures by Erland Sommarskog.
If you are using SQL Server 2008 look at the section on Table Parameters and Table Types. You can pass the tables as output parameters, back to the parent.
If you are not on SQL Server 2008, look at the section on Sharing a Temp Table.
You basically create two #TempTables in the parent procedure, and in the child procedure you populate each of the #TempTables and terminate the child procedure. When you are back in the parent procedure each #TempTable has data in it.
As far as I know, there's no way to capture a second result set inside T-SQL.
You could do it from a CLR stored procedure.
I have 2 stored procedures usp_SP1 and usp_SP2. Both of them make use of insert into #tt exec sp_somesp. I wanted to create a 3rd stored procedure which will decide which stored proc to call. Something like:
create proc usp_Decision
(
#value int
)
as
begin
if (#value = 1)
exec usp_SP1 -- this proc already has insert into #tt exec usp_somestoredproc
else
exec usp_SP2 -- this proc too has insert into #tt exec usp_somestoredproc
end
Later, I realized I needed some structure defined for the return value from usp_Decision so that I can populate the SSRS dataset field. So here is what I tried:
Within usp_Decision created a temp table and tried to do "insert into #tt exec usp_SP1". This didn't work out. error "insert exec cannot be nested"
Within usp_Decision tried passing table variable to each of the stored proc and update the table within the stored procs and do "select * from ". That didn't work out as well. Table variable passed as parameter cannot be modified within the stored proc.
Please suggest what can be done.
Can you modify usp_SP1 and usp_SP2?
If so, in usp_Decision, create a local temporary table with the proper schema to insert the results:
create table #results (....)
Then, in the called procedure, test for the existence of this temporary table. If it exists, insert into the temporary table. If not, return the result set as usual. This helps preserve existing behavior, if the nested procedures are called from elsewhere.
if object_id('tempdb..#results') is not null begin
insert #results (....)
select .....
end
else begin
select ....
end
When control returns to the calling procedure, #results will have been populated by the nested proc, whichever one was called.
If the result sets don't share the same schema, you may need to create two temporary tables in usp_Decision.
Have you had a look at table-valued user-defined functions (either inline or multi-statement)? Similar to HLGEM's suggestion, this will return a set which you may not have to insert any where.
Not a fan of global temp tables in any event (other processes can read these table and may interfere with the data in them).
Why not have each proc use a local temp table and select * from that table as the last step.
Then you can insert into a local temp table in the calling proc.
esimple example
create proc usp_mytest1
as
select top 1 id into #test1
from MYDATABASE..MYTABLE (nolock)
select * from #test1
go
--drop table #test
create proc usp_mytest2
as
select top 10 MYTABLE_id into #test2
from MYDATABASE..MYTABLE (nolock)
select * from #test2
go
create proc usp_mytest3 (#myvalue int)
as
create table #test3 (MYTABLE_id int)
if #myvalue = 1
Begin
insert #test3
exec ap2work..usp_mytest1
end
else
begin
insert #test3
exec ap2work..usp_mytest2
end
select * from #test3
go
exec ap2work..usp_mytest3 1
exec ap2work..usp_mytest3 0
See this blog article for one wortkaround (uses OPENROWSET to essentially create a loopback connection on which one of the INSERT EXEC calls happens)