How to use Table Variable in Dynamic Query - sql

I want to use Table Variable instead of Temp Table but My main query construction is Dynamic .
Dynamic query is in single quote so how can I fetch data from #TableVariable.
I dont want to remove dynamic query because some of parameter will added later.
e.g. following is error code , where I have wrote table variable into Dynamic Query........
/*Declare Table Variable*/
DECLARE #TempVehicles TABLE
(
[VehicleID] INT
)
/*Insert data into Table Variable*/
INSERT INTO #TempVehicles
(
[VehicleID]
)
SELECT VehicleID
FROM tbl_Vehicles
/*Dynamic Query and Main SQL Construction*/
DECLARE #SQL NVARCHAR(MAX)
SET #SQL ='SELECT Cust_ID,A.VehicleID,GISInfo
FROM #TempVehicles A INNER JOIN tbl_GISData B ON A.VehicleID=B.VehicleID'
EXECUTE SP_EXECUTESQL #SQL
Help me , in this .
Thanks in Advance.

Try This :
CREATE TYPE IntegerTableType AS TABLE (ID INT);
go
DECLARE #TempVehicles IntegerTableType;
INSERT #TempVehicles
values (1);
DECLARE #SQL NVARCHAR(MAX);
SET #SQL ='SELECT *
FROM #TempVehicles;';
EXECUTE SP_EXECUTESQL #SQL,N'#TempVehicles IntegerTableType READONLY',
#TempVehicles;

As an alternate solution you can use #TempVehicles instead of storing it in variable.
SELECT VehicleID
into #TempVehicles
FROM tbl_Vehicles
/*Dynamic Query and Main SQL Construction*/
DECLARE #SQL NVARCHAR(MAX)
SET #SQL ='SELECT Cust_ID,A.VehicleID, GISInfo
FROM #TempVehicles A INNER JOIN tbl_GISData B ON A.VehicleID=B.VehicleID;
Drop Table #TempVehicles'
EXECUTE SP_EXECUTESQL #SQL
Try and check whether it meets your requirement.

Related

not able to use sp_executesql command

I need to execute below query
SELECT *, IDENTITY( int ) AS IDColumn INTO #SmootheningTable FROM #TableName
where #SmootheningTable is temporary table
and #TableName is name of table
I need to use command either EXEC or sp_executesql to execute.
If I use EXEC, I wont be able to use #SmootheningTable in later portion of my stored procedure.
And while trying sp_executesql, I am getting error stating #statement error.
How can I use sp_executesql for above given query.
Or is there any other way to execute?
this is the query I am using
DECLARE #TablePlaceHolder VARCHAR(50)='';
DECLARE #SmootheningQuery NVARCHAR(max) = 'SELECT *, IDENTITY( int ) AS IDColumn INTO #SmootheningTable FROM #TablePlaceHolder';
EXEC sp_executesql #SmootheningQuery, N'#TablePlaceHolder varchar(50)', #PlanDetailTempTableName
and i am getting below error
Must declare the table variable "#TablePlaceHolder".
Thanks in advance
There are two issues in your code:-
First : Putting the variable name inside the string, put in out like next:-
instead of this line:-
DECLARE #SmootheningQuery NVARCHAR(max) = 'SELECT *, IDENTITY( int ) AS
IDColumn INTO #SmootheningTable FROM #TablePlaceHolder';
Type this line:-
DECLARE #SmootheningQuery NVARCHAR(max) = 'SELECT *, IDENTITY( int ) AS
IDColumn INTO #SmootheningTable FROM ' + #TablePlaceHolder;
Second: Don't use local temp table within sp_executeSql,
The Local temporary table [with one hash # ] is visible in current session only, use global temporary tables instead [with two hashes ## ] are visible in all sessions,
So instead of
#SmootheningTable
Type
##SmootheningTable
Demo (All Code): -
Create table MyTable (id int , name nvarchar(100))
go
insert into MyTable values (1, 'Ahmed');
insert into MyTable values (2, 'Abdelqader');
go
declare
#TableName varchar(50),
#MyQuery nvarchar(200)
set #TableName = 'MyTable'
set #MyQuery = 'select * Into ##MYTempTable From ' + #TableName
exec sp_executesql #MyQuery
select * from ##MYTempTable
Result:-
id name
1 Ahmed
2 Abdelqader
Please Try This,
CREATE PROC usp_SmootheningTable
AS
BEGIN
SELECT *, IDENTITY( int ) AS IDColumn INTO #SmootheningTable FROM
TableName
SELECT * FROM #SmootheningTable
END
GO
Please try this out
CREATE TABLE #Temp
(
Columns
)
DECLARE #SQL NVARCHAR(MAX)
DECLARE #TableName VARCHAR(MAX)
SET #TableName = 'TableName'
SET #SQL = 'SELECT TOP 10 * FROM '+#TableName
INSERT INTO #Temp
EXEC SP_EXECUTESQL #SQL
SELECT * FROM #Temp

Dynamic SQL Result INTO #Temp Table

I have to Execute a dynamic SQL SELECT Query And put Results into a #TempTable.
DECLARE #StateId CHAR(3)='StateID';
DECLARE #DeptId CHAR(15)='DeptID';
DECLARE #Query VARCHAR(MAX)='Select Columns With Joins Passed From Front End'
DECLARE #Where VARCHAR(500);
DECLARE #FinalQuery VARCHAR(MAX)='';
SET #Where='Some Where Condition';
SET #FinalQuery='SELECT '+#Query+' '+#Where+''
EXEC(#FinalQuery) -- Want To INSERT THIS Result IN SOME `#TempTable`
-- SO that I can perform Some Operations On `#TempTable`
ALSO No Of columns returned From Dynamic SQL SELECT Are Dynamic.
Thanks,
try the below example
DECLARE #StateId CHAR(3)='StateID';
DECLARE #DeptId CHAR(15)='DeptID';
DECLARE #Query VARCHAR(MAX)='*' -- here you pass your query
DECLARE #Where VARCHAR(500);
DECLARE #FinalQuery VARCHAR(MAX)='';
SET #Where='from tablename where condition';
SET #FinalQuery='SELECT '+#Query+' INTO #temptablename '+#Where;
EXEC(#FinalQuery)
Note
:If you need to use temtable after sp execution then use ## rather than # then we can access it or we can use persistent temporary table
Please make sure that your query statements is correctly.
Try this in your stored procedure and check the output results ( copy the result and execute it)
....
SET #FinalQuery='SELECT '+#Query+' '+#Where+'
PRINT(#FinalQuery)
....
You can use the SQL Profiler tool to debug
Try this...
First create the temp table which you need for further calculation.
CREATE TABLE #TEMP
(
STATEID INT,
DEPTID INT
)
DECLARE #STATEID CHAR(10)='STATEID';
DECLARE #DEPTID CHAR(15)='DEPTID';
DECLARE #QUERY VARCHAR(MAX)='INSERT INTO #TEMP_TABLE
SELECT COLUMNS WITH JOINS PASSED FROM FRONT END'
DECLARE #WHERE VARCHAR(500);
DECLARE #FINALQUERY VARCHAR(MAX)=''
SET #WHERE='SOME WHERE CONDITION'
SET #FINALQUERY=+#QUERY+' '+#WHERE+'' -- REMOVED SELECT
EXEC(#FINALQUERY)

How to execute a SQL String that references a table variable?

I have a table variable in SQL Server 2008
DECLARE #specsAndModel TABLE
(
specName VARCHAR(50)
,specVal VARCHAR(50)
)
INSERT INTO #specsAndModel
VALUES('[modelNumber]', 'F00-B4R')
Then, I later build a string called #query, which I ultimately try to pass into EXECUTE, as in the following example:
DECLARE #query NVARCHAR(MAX);
SET #query = 'SELECT specName, specVal FROM #specsAndModel'
EXECUTE(#query)
However, SQL Server gives me the error message: Must declare the table variable "#specsAndModel".
After searching around, I think this might be related to the execution context, but I haven't been able to resolve the problem.
Is it even possible for me to use a table variable in a call to the execute function?
The table you are creating is a table variable which is not available outside of its initial scope. There are a few ways to fix this:
Create a Global Temp Table (Disclaimer: this can cause problems if more that one user attempts to run this at the same time.):
create table ##specsAndModel
(
specName VARCHAR(50)
,specVal VARCHAR(50)
)
INSERT INTO ##specsAndModel
VALUES('[modelNumber]', 'F00-B4R')
DECLARE #query NVARCHAR(MAX);
SET #query = 'SELECT specName, specVal FROM ##specsAndModel'
EXECUTE(#query)
Create a Local Temp Table instead of global:
create table #specsAndModel
(
specName VARCHAR(50)
,specVal VARCHAR(50)
)
INSERT INTO #specsAndModel
VALUES('[modelNumber]', 'F00-B4R')
DECLARE #query NVARCHAR(MAX);
SET #query = 'SELECT specName, specVal FROM #specsAndModel'
EXECUTE(#query)
Execute the create table inside of your dynamic SQL (ugly):
DECLARE #query NVARCHAR(MAX);
SET #query = 'DECLARE #specsAndModel TABLE
(
specName VARCHAR(50)
,specVal VARCHAR(50)
)
INSERT INTO #specsAndModel
VALUES(''[modelNumber]'', ''F00-B4R'')
SELECT specName, specVal FROM #specsAndModel'
exec(#query)
Instead of using a temp table, create an actual table and then drop it when done (Disclaimer: this can cause problems if more that one user attempts to run this at the same time.):
create TABLE specsAndModel
(
specName VARCHAR(50)
,specVal VARCHAR(50)
)
INSERT INTO specsAndModel
VALUES('[modelNumber]', 'F00-B4R')
DECLARE #query NVARCHAR(MAX);
SET #query = 'SELECT specName, specVal FROM specsAndModel'
EXECUTE(#query)
drop table specsAndModel
Here is an link to a discussion about temp tables and table variables:
Should I use a #temp table or a #table variable?
Edit: You can pass in a table variable using sp_executesql:
create type specsAndModel as table (
specName VARCHAR(50)
,specVal VARCHAR(50)
)
go
declare #t specsAndModel
insert #t VALUES('[modelNumber]', 'F00-B4R')
exec sp_executesql N'select specName, specVal from #var', N'#var specsAndModel readonly', #t
Using either the global ##temp tables and a permanent table run risks in that if more than one users attempts to run the process, there could be conflicts.
You are safer using either a local #temp table or passing the table variable using sp_executesql.
You also have to create your table variable inside the in the string.
DECLARE #query NVARCHAR(MAX);
SET #query = 'DECLARE #specsAndModel TABLE ( specName VARCHAR(50) ,specVal VARCHAR(50))'
SET #Query = #Query + ' INSERT INTO #specsAndModel VALUES(''modelNumber'',''abcd''); SELECT specName, specVal FROM #specsAndModel'
EXEC (#query)

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;

Pass a TABLE variable to sp_executesql

I'm trying to pass a TABLE variable to the sp_executesql procedure:
DECLARE #params NVARCHAR(MAX)
SET #params = '#workingData TABLE ( col1 VARCHAR(20),
col2 VARCHAR(50) )'
EXEC sp_executesql #sql, #params, #workingData
I get the error:
Msg 156, Level 15, State 1, Line 1
Incorrect syntax near the keyword 'TABLE'.
I tried omitting the column specification after 'TABLE'. I also tried to declare the table as a variable inside the dynamic SQL. But no luck...
Seems to me that TABLE variables aren't allowed to be passed as parameters in this procedure?. BTW: I'm running MSSQL2008 R2.
I'm not interested in using a local temp table like #workingData because I load the working data from another procedure:
INSERT INTO #workingData
EXEC myProc #param1, #param2
Which I cannot do directly into a temp varaible (right?)...
Any help appreciated!
If you are using SQL Server 2008, to pass a table variable to a stored procedure you must first define the table type, e.g.:
CREATE TYPE SalesHistoryTableType AS TABLE
(
[Product] [varchar](10) NULL,
[SaleDate] [datetime] NULL,
[SalePrice] [money] NULL
)
GO
or use an existing table type stored in the database.
Use this query to locate existing table types
SELECT * FROM sys.table_types
To use in an stored procedure, declare an input variable to be the table:
CREATE PROCEDURE usp_myproc
(
#TableVariable SalesHistoryTableType READONLY
)
AS BEGIN
--Do stuff
END
GO
Populate the table variable before passing to the stored procedure:
DECLARE #DataTable AS SalesHistoryTableType
INSERT INTO #DataTable
SELECT * FROM (Some data)
Call the stored procedure:
EXECUTE usp_myproc
#TableVariable = #DataTable
Further discussions here.
OK, this will get me what I want, but surely isn't pretty:
DECLARE #workingData TABLE ( col1 VARCHAR(20),
col2 VARCHAR(20) )
INSERT INTO #workingData
EXEC myProc
/* Unfortunately table variables are outside scope
for the dynamic SQL later run. We copy the
table to a temp table.
The table variable is needed to extract data directly
from the strored procedure call above...
*/
SELECT *
INTO #workingData
FROM #workingData
DECLARE #sql NVARCHAR(MAX)
SET #sql = 'SELECT * FROM #workingData'
EXEC sp_executesql #sql
There must be a better way to pass this temporary resultset into sp_executesql!?
Regards
Alex
While this may not directly answer your question, it should solve your issue overall.
You can indeed capture the results of a Stored Procedure execution into a temporary table:
INSERT INTO #workingData
EXEC myProc
So change your code to look like the following:
CREATE TABLE #workingData ( col1 VARCHAR(20),
col2 VARCHAR(20) )
INSERT INTO #workingData
EXEC myProc
DECLARE #sql NVARCHAR(MAX)
SET #sql = 'SELECT * FROM #workingData'
EXEC sp_executesql #sql
Regards,
Tim
Alter PROCEDURE sp_table_getcount
#tblname nvarchar(50) ,
#totalrow int output
AS
BEGIN
Declare #params nvarchar(1000)
Declare #sql nvarchar(1000)
set #sql = N'Select #cnt= count(*) From #tbl'
set #params = N'#tbl nvarchar(50) , #cnt int OUTPUT'
Exec sp_executesql #sql , #params ,#tbl=#tblname , #cnt = #totalrow OUTPUT
END
GO
Please note that the above code will not work as table as a object is out of the scope.It will give you the error: must declare table variable.In order to work around we can do the following.
Alter PROCEDURE sp_table_getcount
#tblname nvarchar(50) ,
#totalrow int output
AS
BEGIN
Declare #params nvarchar(1000)
Declare #sql nvarchar(1000)
set #sql = N'Select #cnt= count(*) From dbo.' + #tblname
set #params = N'#cnt int OUTPUT'
Exec sp_executesql #sql , #params , #cnt = #totalrow OUTPUT
END
GO
So-called TableType is tricky. #Alex version should work. However, to simplify and faster performance, go check sys.tables for matching table name while not compromise security and performance.
Here it is
create proc [dbo].Test11
#t1 AS nvarchar(250), #t2 nvarchar(250)
AS
BEGIN
SET nocount ON;
DECLARE #query AS nvarchar(MAX)
if exists (select * from sys.tables where name = #t1) and
exists (select * from sys.tables where name = #t2)
begin
SET #query = N'select * FROM '+ #t1 + N' join ' + #t2 + N' ON ...' ;
select 'Safe and fast'
print #query
exec sp_executesql #query
end
else
select 'Bad, no way Jose.'
SET nocount OFF;
END
GO