Insert into temp table from exec call stored procedure - sql

I have a stored procedure where I insert a table into a temporary table and then I read that temp table row by row using a cursor:
USE [TEST_DB]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[returnValidationFailures]
AS
BEGIN
SET NOCOUNT ON;
SELECT TOP 0 * INTO TempTbl FROM USER
DECLARE cursor1 CURSOR FAST_FORWARD FOR
SELECT *
FROM USER
OPEN cursor1
INSERT INTO TempTbl
EXEC ('fetch next from cursor1')
WHILE ##FETCH_STATUS = 0
INSERT INTO TempTbl
EXEC ('fetch next from cursor1')
CLOSE cursor1
DEALLOCATE cursor1
SELECT *
FROM TempTbl
DROP TABLE TempTbl
END
What I want here is to send the table name through a paramater like:
#TableNameParam varchar(10)
And then insert into temp table like:
SELECT TOP 0 * INTO TempTbl FROM #TableNameParam
DECLARE cursor1 CURSOR FAST_FORWARD FOR
SELECT *
FROM #TableNameParam
This doesn't work (obviously). But every other method I tried didn't work.
Is there any way I can set the data of an EXEC call like:
EXEC ('SELECT * FROM ' + #TableNameParam
' WHERE STATUS=1')
into the temp table?
Note: I DO NOT know the table structure.

I'm not very sure I understand what is your final scope, but my advise is to use a set-based approach.
To respond directly to you question, you should take into account the usage of temporary tables (#TempTable) instead of table variables (#TempTable).
EXEC ('SELECT * FROM ' + #TableNameParam + ' WHERE STATUS=1')
How is your data obtained in your temporary table?

Related

Replicate SQL row with same data but not defining all columns

Is it possible to do a SQL query where I can take let's say all columns form the row for user 'A' and copy them into row for user 'B' without defining the column names.
For an Example, this will not be against speed or intense data, but to help these tasks be functional instead of doing them redundantly over and over. The params for base user and target user would be the stored procedure params.
Declare #BaseUserId varchar(50),
#TargetUserId varchar(50),
#ColumnName varchar(100)
Declare columnNameCursor Cursor For SELECT c.name
FROM sys.columns c
WHERE c.object_id = OBJECT_ID('dbo.EmployeeMenuAccess')
--Opens the cursor now for loop reading
Open columnNameCursor
Fetch next From columnNameCursor into #ColumnName
While ##Fetch_Status=0 Begin
update DocSS set #ColumnName = (select #ColumnName from DocSS where
Username = #BaseUserId) where Username = #TargetUserID
Fetch next From c into #ColumnName
End
Close columnNameCursor
Deallocate columnNameCursor
Thanks in advance.
CREATE TABLE Test
(id int, name char(10))
;
INSERT INTO Test VALUES(1, 'first');
INSERT INTO Test VALUES(2, 'second');
BEGIN TRAN T1;
SELECT * INTO Temp FROM Test WHERE id = 1;
UPDATE Temp SET id = (SELECT MAX(id)+1 FROM Test);
INSERT INTO Test SELECT * FROM Temp;
DROP TABLE Temp;
COMMIT TRAN T1;
SELECT * FROM Test;
Try this

How to insert result of Stored Procedure into Temp Table without declaring Temp Table Columns

I want to insert the values of stored procedure into a temp table without predefining the columns for the temp table.
Insert Into #Temp1 Exec dbo.sp_GetAllData #Name = 'Jason'.
How can I do this ? I saw an option as below but can I do it without mentioning the server name ?
SELECT * INTO #TestTableT FROM OPENROWSET('SQLNCLI', 'Server=localhost;Trusted_Connection=yes;',
'EXEC tempdb.dbo.GetDBNames')
-- Select Table
SELECT *
FROM #TestTableT;
I could not find a possible solution without defining temp table schema and writing server name. So, I changed the code and the queries to handle with only known schema. Code example is as below
CREATE TABLE #TestTable ([name] NVARCHAR(256), [database_ID] INT);
INSERT INTO #TestTable
EXEC GetDBNames
SELECT * FROM #TestTable;
As provided in the link https://blog.sqlauthority.com/2013/05/27/sql-server-how-to-insert-data-from-stored-procedure-to-table-2-different-methods/
No-one said it had to be pretty:
CREATE PROCEDURE p AS
SELECT 1 as x, 2 as y, 3 as z
GO
DECLARE c CURSOR FOR
SELECT
name, system_type_name
FROM sys.dm_exec_describe_first_result_set_for_object(OBJECT_ID('p'), 0);
DECLARE #name sysname, #type sysname;
CREATE TABLE #t(fake int)
OPEN c
FETCH NEXT from c into #name, #type
WHILE (##FETCH_STATUS = 0)
BEGIN
EXEC ('ALTER TABLE #t ADD ' + #name + ' ' + #type)
FETCH NEXT from c into #name, #type
END
CLOSE C
DEALLOCATE c
ALTER TABLE #t DROP COLUMN fake;
INSERT INTO #t EXEC p;
GO

T-SQL: Update temp table using "from variable" query

I have a linked server connecting to a Lotus notes database as the source. The destination will be an MS SQL database.
I have two temp tables. The first temp table is pulling in the table names from a linked server. From there, I want to do a record count for each table and store that value into the second temp table beside the table name.
I am having trouble trying to run a loop or cursor for each table name and then updating the second temp table with the record count for each table name.
Right now I am getting an error "Incorrect syntax near 'Execute'". SET record_count = Execute(#sqlCommand)
Declare #DB_tables table (
table_cat varchar(1500),
table_schem varchar(1500),
table_name varchar(1500),
table_type varchar(1500),
remarks varchar(1500)
)
Declare #temp_table table (
table_name varchar(1500),
record_count varchar(255),
drop_script varchar(1500),
update_script varchar(1500)
)
--Load Initial data from linked server database
insert into #DB_Tables
exec sp_tables_ex [LINKED_SERVER_DB]
--Load table name from Stored Procedure
INSERT INTO #temp_table (table_name)
SELECT table_name from #DB_Tables
--select * from #temp_table
--Variable to hold each table name in a loop or cursor
declare #tbl_name varchar(1500)
--declare #sqlCommand varchar(1500)
declare cur cursor for select table_name from #DB_Tables
Open cur
--Loop through each table name from the first temp table
--then update the second temp table (#temp_table) with the record count
FETCH NEXT FROM cur into #tbl_name
While ##FETCH_STATUS = 0 BEGIN
declare #sqlCommand varchar(1500)
--query used to get the record count from the frist temp table (#DB_tables)
SET #sqlCommand = 'select count(*) from '+#tbl_name
UPDATE #temp_table
SET record_count = Execute(#sqlCommand)
END
CLOSE cur
Deallocate cur
select * from #temp_table
It's not easy to use table variables with execute because the dynamic SQL is executed in the different context and doesn't see the variable and you can't assign results from execute that way.
You can either insert the results into a table variable with this syntax:
insert into #temp_table
execute ('select ' + #tbl_name + ', count(*) from ' + #tbl_name ...)
Or use temp. tables, since then you can refer them also inside the dynamic SQL, so you could do something like:
create table #temp_table (
table_name varchar(1500),
record_count varchar(255),
drop_script varchar(1500),
update_script varchar(1500)
)
...
Execute('update #temp_table set record_count = (select count(*) from '
+#tbl_name+') where table_name = '''+#tbl_name+''')

Using EXEC inside SELECT statement in SQL Server

I need to use exec inside of select clause. The query for the exec is created according to the columns of the table to on which select clause if used. What i want to do is something like following:
SELECT distinct
MTMain.[TableName],
MTMain.[TableFKey],
(select IsActive (exec GetStringForIsActive MTMain.[TableName],MTMain.[TableFKey]))
FROM
[MasterTableForLanguage] MTMain
Here, GetStringForIsActive is the stored procedure I want to execute for every row selected from MasterTableForLanguage.
The stored procedure will use EXEC to execute the following string
select IsActive from [TableName] where PKID= cast([TableFKey] as int)
TableName and TableFKey will be inputs of the stored procedure.
If you can modify your Stored Procedure GetStringForIsActive to return TableName, TableFKey and IsActive, you can use a cursor to get execute it for each row and add the results to a temp table.
ie:
exec GetStringForIsActive 'TableName', 'TableFKey'
returns
select [TableName], [TableFKey], IsActive from [TableName] where PKID= cast([TableFKey] as int)
The code would be like this:
declare #TableName nvarchar(50)
declare #TableFKey nvarchar(50)
declare #Results table (TableName nvarchar(50), TableFKey nvarchar(50), IsActive bit)
declare TableCursor cursor fast_forward for
select TableName, TableFKey from MasterTableForLanguage
open TableCursor
fetch next from TableCursor into #TableName, #TableFKey
if ##FETCH_STATUS <> -1
print 'MasterTableForLanguage check'
while (##FETCH_STATUS <> -1)
begin
insert into #Results
exec GetStringForIsActive #TableName, #TableFKey
fetch next from TableCursor into #TableName, #TableFKey
end
close TaleCursor
deallocate TableCursor
select * from #Results
use Functions instead of Stored procedures in SELECT clause.
Edited:
create that function
CREATE FUNCTION function1 (#TableName nvarchar(10),#TableFKey nvarchar(10))
RETURNS nvarchar(100) AS
BEGIN
-- do whatever here
END
then
SELECT distinct
MTMain.[TableName],
MTMain.[TableFKey],
function1(MTMain.[TableName],MTMain.[TableFKey])
FROM
[MasterTableForLanguage] MTMain
Does this make sense?
Well, I think to answer the full question, I don't believe a stored procedure would EXEC a SELECT statement, it would simply perform the SELECT.
You EXEC your current proc and pass it vars, and it returns a value BASED ON the select statement it runs. It's not EXEC'ing that statement, simply performing a select. I have several stored procs I use daily in some SQL agent processes, they all perform selects to query various tables, and none of them call an EXEC to perform those actions. This is my own example:
CREATE PROCEDURE [myproc]
#job_ident INT
AS
BEGIN
SET NOCOUNT ON;
...
SELECT TOP(1) #filter_type = filter_type FROM [place] WHERE [ident] = #job_ident
...
END
As mentioned previously, the most effective way to perform your query would be to perform that select inside a function, something similar to this I think will do:
CREATE FUNCTION ThisFunction (
#TableName nvarchar(10),
#TableFKey nvarchar(10)
)
RETURNS nvarchar(100)
AS
BEGIN
RETURN
(
select IsActive from [TableName] where PKID= cast([TableFKey] as int)
)
END
You could then do exactly as you want...
SELECT distinct
MTMain.[TableName],
MTMain.[TableFKey],
ThisFunction(MTMain.[TableName],MTMain.[TableFKey])
FROM
[MasterTableForLanguage] MTMain

Execute sp_executeSql for select...into #table but Can't Select out Temp Table Data

Was trying to select...into a temp Table #TempTable in sp_Executedsql.
Not its successfully inserted or not but there Messages there written
(359 row(s) affected) that mean successful inserted?
Script below
DECLARE #Sql NVARCHAR(MAX);
SET #Sql = 'select distinct Coloum1,Coloum2 into #TempTable
from SPCTable with(nolock)
where Convert(varchar(10), Date_Tm, 120) Between #Date_From And #Date_To';
SET #Sql = 'DECLARE #Date_From VARCHAR(10);
DECLARE #Date_To VARCHAR(10);
SET #Date_From = '''+CONVERT(VARCHAR(10),DATEADD(d,DATEDIFF(d,0,GETDATE()),0)-1,120)+''';
SET #Date_To = '''+CONVERT(VARCHAR(10),DATEADD(d,DATEDIFF(d,0,GETDATE()),0)-1,120)+''';
'+ #Sql;
EXECUTE sp_executesql #Sql;
After executed,its return me on messages (359 row(s) affected).
Next when trying to select out the data from #TempTable.
Select * From #TempTable;
Its return me:
Msg 208, Level 16, State 0, Line 2
Invalid object name '#TempTable'.
Suspected its working only the 'select' section only. The insert is not working.
how fix it?
Using a global temporary table in this scenario could cause problems as the table would exist between sessions and may result in some problems using the calling code asynchronously.
A local temporary table can be used if it defined before calling sp_executesql e.g.
CREATE TABLE #tempTable(id int);
execute sp_executesql N'INSERT INTO #tempTable SELECT myId FROM myTable';
SELECT * FROM #tempTable;
Local temporary table #table_name is visible in current session only, global temporary ##table_name tables are visible in all sessions. Both lives until their session is closed.
sp_executesql - creates its own session (maybe word "scope" would be better) so that's why it happens.
In your #sql string, don't insert into #TempTable. Instead, call your SELECT statement without an INSERT statement.
Finally, insert the results into your temporary table like so:
INSERT INTO #tmpTbl EXEC sp_executesql #sql
Also, you'll need to declare the temporary table if you use this approach
DECLARE #tmpTbl TABLE (
//define columns here...
)
your temp table in dynamic SQL is out of scope in the non dynamic SQL part.
Look here how to deal with this: A bit about sql server's local temp tables
Temporary tables only live as long as the connection that creates them. I would expect that you're unintentionally issuing the select on a separate connection. You can test this by momentarily doing your insert into a non-temporary table and seeing if your data is there. If that is the case you can go back to your original solution and just be sure to pass the connection object to your select.
declare #sql varchar(1000)
set #sql="select * into #t from table;"
set #sql =#sql + "select * from #t;"
execute SP_EXECUTESQL #sql
This worked for me
declare #sql nvarchar(max)
create table #temp ( listId int, Name nvarchar(200))
set #sql = 'SELECT top 10 ListId, Name FROM [V12-ListSelector].[dbo].[List]'
insert into #temp
exec sp_executesql #sql
select * from #temp
drop table #temp
To work around this issue use a CREATE TABLE #TEMPTABLE command first to generate an empty temp table before running sp_executesql. Then run the INSERT INTO #TEMPTABLE with sp_executesql. This will work. This is how I overcome this problem as I have a setup in which all my queries are usually run via sp_executesql.
This one worked for me:
DECLARE #Query as NVARCHAR(MAX);
SET #Query=(SELECT * FROM MyTable) ;
SET #Query=(SELECT 'SELECT * INTO dbo.TempTable FROM ('+#Query +') MAIN;');
EXEC sp_executesql #Query;
SELECT * INTO #TempTable FROM dbo.TempTable;
DROP TABLE dbo.TempTable;
SELECT * FROM #TempTable;
Note, from T-SQL 2021 onwards, dm_exec_describe_first_result_set() can be used to build a temporary table in the right shape to INSERT INTO - as it gives you the column names and types that will be returned from your dynamic SELECT or EXEC ... so you can build dynamic SQL to ALTER a temporary table into the shape you need.
DECLARE #strSQL NVarChar(max) = 'EXEC [YourSP] #dtAsAt=''2022-11-09'', #intParameter2=42'
--*** Build temporary table: create it with dummy column, add columns dynamically
--*** using an exec of sys.dm_exec_describe_first_result_set() and dropping the dummy column
DROP TABLE IF EXISTS #tblResults;
CREATE TABLE #tblResults ([zz] INT);
DECLARE #strUpdateSQL NVarChar(max);
SELECT #strUpdateSQL = STRING_AGG( CONCAT( 'ALTER TABLE #tblResults ADD ',
QUOTENAME([name]), ' ',
[system_type_name], ';')
, ' ') WITHIN GROUP (ORDER BY [column_ordinal])
FROM sys.dm_exec_describe_first_result_set (#strSQL, NULL, 0)
SET #strUpdateSQL += 'ALTER TABLE #tblResults DROP COLUMN [zz];'
EXEC (#strUpdateSQL);
--*** Now we have #tblResults in the right shape to insert into, and use afterwards
INSERT INTO #tblResults EXEC (#strSQL);
SELECT * FROM #tblResults;
--*** And tidy up
DROP TABLE IF EXISTS #tblResults;