Pass a TABLE variable to sp_executesql - sql

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

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

How to write Select query with dynamic table name in Stored Procedure?

I am writing a stored-procedure. But the table name is dynamic in this procedure. I want to get row number from my variable table. But where will I set #rownumber with return of select query?
Create Proc update_eMail
(#tablename nvarchar(50),
#columnname nvarchar(50))
AS
Begin
Declare #q_getrowNumber NVARCHAR(MAX)
Declare #rownumber int
SELECT #rownumber = Count(ID) FROM quotename(#tablename) // doesnt work
END
Thanks in advance
Here is one way to achieve the goal using dynamic sql
declare #sql NVARCHAR(4000)= ''
set #sql = 'SELECT #rownumber = Count(ID) FROM '+ quotename(#tablename)
exec sp_executesql #sql, N'#rownumber int output',#rownumber output
You write wrong Procedure for dynamic query
Try This. It will Work.
ALTER PROC update_eMail(#tablename NVARCHAR(50))
AS
BEGIN
DECLARE #RowNumber NVARCHAR(MAX)=''
set #RowNumber='select Count(ID) FROM '+#tablename+''
exec(#RowNumber)
END
OR Try below Code in your Query
ALTER PROC update_eMail1
(
#tablename NVARCHAR(50)
)
AS
BEGIN
DECLARE #sql NVARCHAR(4000)= '',#rownumber INT
SET #sql = 'SELECT #rownumber = Count(ID) FROM '+quotename(#tablename)
EXEC sp_executesql #sql, N'#rownumber int output',#rownumber OUTPUT
SELECT #rownumber
END
This one will be easiest for you:
Create Proc update_eMail
#tablename nvarchar(50)
AS
Begin
EXEC ( 'SELECT Count(ID) FROM '+#tablename+'')
END

Stored procedure with a parameter in FROM clause

Is it possible to create a stored procedure that uses a parameter in the FROM clause?
For example:
CREATE PROCEDURE [dbo].[GetMaxId]
#id varchar(50)
#table varchar(50)
AS
BEGIN
SELECT MAX(#id)
FROM #table
END
You cannot pass identifiers as parameters into a query (neither table names nor column names). The solution is to use dynamic SQL. Your syntax suggests SQL Server, so this would look like:
CREATE PROCEDURE [dbo].[GetMaxId] (
#id varchar(50)
#table varchar(50)
)
AS
BEGIN
DECLARE #sql NVARCHAR(MAX);
SET #sql = N'SELECT MAX(#id) FROM #table';
SET #sql = REPLACE(REPLACE(#sql, '#id', QUOTENAME(#id)), '#table', QUOTENAME(#table));
EXEC sp_executesql #sql;
END; -- GetMaxId

Why does storing a value from sp_executesql return NULL?

Once more I stumble upon an SQL mishappening. The following code:
create trigger tc_trigger_olt_UPDATE on tick_orderline_type
for update as
declare #UserId varchar(32) --
declare #ClientId varchar(32) --
declare #CaseId varchar(32) --
declare #TableName varchar(64) --Used
declare #RecordId varchar(512) --Used
declare #Descr varchar(128) --
declare #RemoteIP varchar(16) --Used
select #TableName = object_name(parent_id) from sys.triggers where object_id = ##procid
select #RemoteIP = client_net_address from sys.dm_exec_connections where Session_id = ##SPID
if exists(select * from information_schema.columns where table_name = #TableName and column_name = 'id')
begin
select #RecordId = id from inserted
end
declare #sql nvarchar(max)
set #sql = 'select case_id from '+#TableName+' where id = '''+#RecordId+'''';
exec sp_executesql #sql, N'#out_param varchar(32) OUTPUT', #out_param=#CaseId OUTPUT
execute update_tick_orderline_type #UserId, #ClientId, #CaseId, #TableName, #RecordId, #Descr, #RemoteIP
Is used for filling and audit-table in SSMS, which works. It stores which table, which record, on which date and from which IP-Address the table has been edited.
I am currently trying to get which client's data, for which case, has been edited using the following snipped from above:
declare #sql nvarchar(max)
set #sql = 'select case_id from '+#TableName+' where id = '''+#RecordId+'''';
exec sp_executesql #sql, N'#out_param varchar(32) OUTPUT', #out_param=#CaseId OUTPUT
In my Results window (the one that shows select statement results), I can see that the #sql statement has selected the correct case_id; storing it in the #CaseId variable however, returns NULL. Once I have the #CaseId I can get the #ClientId, so I'm stumped here.
Why is the statement outputting the correct case_id, but stores it as NULL?
A little sidenote: the case_id is only being output when the exec statement is present, otherwise it is not
I managed to fix my own predicament, by changing the previous 'select x from #TableName' block, to this:
declare #sql nvarchar(max)
declare #params nvarchar(max)
set #params = N'#iCaseId varchar(max) output'
select #sql = N'select #iCaseId = case_id from '+quotename(#TableName)+
' where id = '''+#RecordId+''''
execute sp_executesql #sql, #params, #CaseId output
What changed?
I declared an additional #params variable, for readability
Instead of set I select-ed the #sql variable
quotename now surrounds the #TableName variable
instead of the last param for sp_executesql being #x = #y output I simply replaced it with #y output
Conclusion
After several tests (mainly removing some of the changes), I can conclude that the last point on that list was key to solving the issue.
With quotename removed from the statement, I still manage to save the result in a variable, and since the #param variable is not mandatory, but rather a personal preference, it also had no real significance.

sp_executesql and table output

I'm writing a stored procedure in SQL Server 2005, at given point I need to execute another stored procedure. This invocation is dynamic, and so i've used sp_executesql command as usual:
DECLARE #DBName varchar(255)
DECLARE #q varchar(max)
DECLARE #tempTable table(myParam1 int, -- other params)
SET #DBName = 'my_db_name'
SET q = 'insert into #tempTable exec ['+#DBName+'].[dbo].[my_procedure]'
EXEC sp_executesql #q, '#tempTable table OUTPUT', #tempTable OUTPUT
SELECT * FROM #tempTable
But I get this error:
Must declare the scalar variable "#tempTable".
As you can see that variable is declared. I've read the documentation and seems that only parameters allowed are text, ntext and image. How can I have what I need?
PS: I've found many tips for 2008 and further version, any for 2005.
Resolved, thanks to all for tips:
DECLARE #DBName varchar(255)
DECLARE #q varchar(max)
CREATE table #tempTable(myParam1 int, -- other params)
SET #DBName = 'my_db_name'
SET #q = 'insert into #tempTable exec ['+#DBName+'].[dbo].[my_procedure]'
EXEC(#q)
SELECT * FROM #tempTable
drop table #tempTable
SQL Server 2005 allows to use INSERT INTO EXEC operation (https://learn.microsoft.com/en-us/sql/t-sql/statements/insert-transact-sql?view=sqlallproducts-allversions).
You might create a table valued variable and insert result of stored procedure into this table:
DECLARE #tempTable table(myParam1 int, myParam2 int);
DECLARE #statement nvarchar(max) = 'SELECT 1,2';
INSERT INTO #tempTable EXEC sp_executesql #statement;
SELECT * FROM #tempTable;
Result:
myParam1 myParam2
----------- -----------
1 2
or you can use any other your own stored procedure:
DECLARE #tempTable table(myParam1 int, myParam2 int);
INSERT INTO #tempTable EXEC [dbo].[my_procedure];
SELECT * FROM #tempTable;
#tempTable's scope is limited to the current procedure.
You could replace the #tempTable with a global temporary table (i.e. ## table), but be very careful with the scope of that table and be sure to drop it when the procedure ends