sp_executesql not executing dynamic sql - sql

I want to get the value of two variables from dynamic sql .
declare #sImport_Table1 table
(
Id int identity(1,1) ,
Zone nvarchar(50),
Sub_Code nvarchar(50),
Geography nvarchar(50),
DayOfWeek nvarchar(50)
)
INSERT INTO #sImport_Table1 SELECT 'A','Z','Geo','SUN'
declare #sZone nvarchar(50)
declare #sSubCode nvarchar(50)
declare #c_Geography nvarchar(50)='Geo'
declare #c_DayOfWeek nvarchar(50)='SUN'
declare #sImport_Table nvarchar(500)='#sImport_Table1'
--SELECT * FROM #sImport_Table1
declare #sQuery nvarchar(4000)
SET #sQuery='SELECT #sZone = Zone, '+
'#sSubCode = Sub_Code
FROM '+ #sImport_Table +
' WHERE Geography ='''+ #c_Geography + '''
AND [DayOfWeek] = '''+ #c_DayOfWeek +''''
PRINT #sQuery
sp_executesql #sQuery)
PRINT #sZone
PRINT #sSubCode

You will need to declare this table variable inside the Dynamic sql as dynamic sql has its own scope, variable declared outside of dynamic sql are not visible inside dynamic sql.
And also use OUTPUT clause when trying to retrieve values from a dynamic sql query. Something like this....
declare #sZone nvarchar(50)
declare #sSubCode nvarchar(50)
declare #c_Geography nvarchar(50)='Geo'
declare #c_DayOfWeek nvarchar(50)='SUN'
declare #sImport_Table nvarchar(500)='#sImport_Table1'
--SELECT * FROM #sImport_Table1
declare #sQuery nvarchar(MAX); --<-- to be on safe side
SET #sQuery = N' declare #sImport_Table1 table
(
Id int identity(1,1) ,
Zone nvarchar(50),
Sub_Code nvarchar(50),
Geography nvarchar(50),
DayOfWeek nvarchar(50)
)
INSERT INTO #sImport_Table1 SELECT ''A'',''Z'',''Geo'',''SUN''
SELECT #sZone = Zone, #sSubCode = Sub_Code ' +
N' FROM #sImport_Table1 ' +
N' WHERE Geography = #c_Geography ' +
N' AND [DayOfWeek] = #c_DayOfWeek '
PRINT #sQuery
EXECUTE sp_executesql #sQuery
,N'#c_Geography nvarchar(50),#c_DayOfWeek nvarchar(50),
#sZone nvarchar(50) OUTPUT, #sSubCode nvarchar(50) OUTPUT'
,#c_Geography , #c_DayOfWeek, #sZone OUTPUT, #sSubCode OUTPUT
SELECT #sSubCode, #sZone

Replace
sp_executesql #sQuery)
with
execute sp_executesql #sQuery
Also in dynamic queries you need to declare variables inside your dynamic string.
Otherwise it will throw error.

Related

T sql - How to store results from a dynamic query using EXEC or EXECUTE sp_executesql

I am trying to write a dynamic query. Let's say i have a table like below, which represents the hierarchy level of a sales agent:
AgentNumber Level1Agent Level2Agent Level3Agent Level4Agent Level5Agent
1122334455 1122334499 1122334488 1122334477 1122334466 1122334455
I want to be able to dynamically select a level based on a specified agent. My EXECUTE statement seems to work correctly, but how do I get the result stored in a variable I can use later? Every answer I have found seems to only get me a success return variable, not the actual query result.
Below is my code:
DECLARE #level INT = 1;
DECLARE #agent CHAR(10) = 1122334455;
DECLARE #colname NVARCHAR(11) = CONCAT('Level',#level,'Agent');
DECLARE #whereclause NVARCHAR(35) = CONCAT('WHERE AgentNumber = ',#agent);
DECLARE #qry NVARCHAR(300) = 'SELECT ' + #colname + ' FROM dbo.TABLE ' + #whereclause;
DECLARE #up NVARCHAR(10);
EXECUTE sp_executesql #qry, #up OUT
SELECT #up
The output of #up is NULL. If I change the last two lines to:
EXECUTE #up = sp_executesql #qry
SELECT #up
Now the output of #up is 0.
I want the output of 1122334499 and I need it stored in a variable that can later be used and inserted into a table.
Here is a fully functional example of how you can do this. Notice this is using a parameterized where clause and quotename around the column name in the dynamic sql to prevent sql injection.
if OBJECT_ID('tempdb..#Agents') is not null
drop table #Agents
create table #Agents
(
AgentNumber char(10)
, Level1Agent char(10)
, Level2Agent char(10)
, Level3Agent char(10)
, Level4Agent char(10)
, Level5Agent char(10)
)
insert #Agents
select '1122334455', '1122334499', '1122334488', '1122334477', '1122334466', '1122334455'
DECLARE #level INT = 3;
DECLARE #agent CHAR(10) = 1122334455;
DECLARE #colname NVARCHAR(11) = CONCAT('Level',#level,'Agent');
declare #agentout char(10)
DECLARE #qry NVARCHAR(300) = 'SELECT #agent_out = ' + quotename(#colname) + ' FROM #Agents WHERE AgentNumber = #agentin';
EXECUTE sp_executesql #qry, N'#agentin char(10), #agent_out char(10) output', #agentin = #agent, #agent_out = #agentout output
select #agentout
You can try this :
DECLARE #level INT = 1;
DECLARE #agent CHAR(10) = 1122334455;
DECLARE #colname NVARCHAR(11) = CONCAT('Level',#level,'Agent');
DECLARE #whereclause NVARCHAR(35) = CONCAT('WHERE AgentNumber = ',#agent);
DECLARE #qry NVARCHAR(300) = 'SELECT #agentout=' + #colname + ' FROM dbo.TABLE ' + #whereclause;
DECLARE #up NVARCHAR(10);
EXECUTE sp_executesql #qry, N'#agentout NVARCHAR(10) OUTPUT', #agentout=#up OUTPUT
SELECT #up
Create a variable table and makes your query insert the results you want there. Something like this:
declare #results table(field1 varchar(max), field2 varchar(max));
declare #sqlStatement varchar(max);
set #sqlStatement = 'insert into #results(field1, field2) select field1, field2 from table';
EXECUTE #sqlStatement;
select * from #results; --It will print the results from your sql statement!

Variable in a dynamic query

I have a problem once I want to run the next query:
declare #j int = 1;
declare #column varchar(255);
set #column = 'last_name';
declare #tmp varchar(255);
declare #query nvarchar(255) = N'select ' + #column + N' from TEST where id = #j'
declare #tbl table(tmp varchar(255))
insert into #tbl
exec sp_executesql #query
select top 1 #tmp = tmp from #tbl
select #tmp
select * from #tbl;
The problem is that if I change the variable #j to a numeric value in the declaration of the #query variable, like this
declare #query nvarchar(255) = N'select ' + #column + N' from TEST where id = 1'
the query is running successfully, if I left the #j variable there, like this
declare #query nvarchar(255) = N'select ' + #column + N' from TEST where id = #j'
I got an error message:
"Must declare the scalar variable #j."
Why? And how can I solve that my query would work with the variable #j?
in the place of ==== where id = #j'
change like this may it works
Convert(nvarchar(2), #j);
You need to cast the #j variable to string. AS its type is INT you should cast it as
CAST(#j AS VARCHAR(12))
Also, you can pass parameters to dynamic SQL statement when it is executed using sp_executesql. In your case it will be something like this:
declare #j int = 1;
declare #column varchar(255);
set #column = 'last_name';
declare #tmp varchar(255);
declare #query nvarchar(255) = N'select ' + #column + N' from TEST where id = #j'
declare #tbl table(tmp varchar(255))
insert into #tbl
exec sp_executesql #query, N'#j INT', #j = #j
select top 1 #tmp = tmp from #tbl
select #tmp
select * from #tbl;
In the following line:
exec sp_executesql #query, N'#j INT', #j = #j
#query is your dynamic T-SQL statement
N'#j INT' is declaration of parameters
#j = #j is parameters assignments
sp_executsql documentation
You can use parameters in the sp_executesql statement like this:
CREATE TABLE TempTable (
TempID INT IDENTITY(1,1) NOT NULL,
SomeDescription VARCHAR(255) NOT NULL,
PRIMARY KEY(TempID))
INSERT INTO TempTable (SomeDescription)
VALUES ('Description 1'),
('Description 2'),
('Description 3')
DECLARE #sql NVARCHAR(500) = 'SELECT * FROM TempTable WHERE TempID = #TempVar',
#params NVARCHAR(500) = '#TempVar int',
#j INT = 2;
EXEC sp_executesql #sql, #params, #TempVar = #j;
declare #j int = 1;
declare #column varchar(255);
set #column = 'last_name';
declare #tmp varchar(255);
declare #query nvarchar(255) = N'select ' + #column + N' from TEST where id ='+ CAST(#j AS VARCHAR(5))
declare #tbl table(tmp varchar(255))
insert into #tbl
exec (#query)
select top 1 #tmp = tmp from #tbl
select #tmp
select * from #tbl;
enter code here

Adding two dynamic variable and store it in INT type column

I've two dynamic variable ...
declare #count nvarchar(max)
declare #totalCount int
set #count = ' ( SELECT COUNT(*) FROM '+ #Table +' where [Name] = '''+ CAST(#Name as nvarchar(max)) +''' ) '
set #totalCount = CAST(CAST(#count as nvarchar(max)) + CAST(#Qty as nvarchar(max)) as INT);
I'm getting an error
conversion failed when converting the nvarchar value to datatype int....
then I need to store #totalCount in [TotalCount] column of type INT ...PLease help
he variable table name requires using dynamic SQL. The example below assigns the computed value to the #totalCount variable using a parameterized query output parameter.
DECLARE
#totalCount int
, #Qty int = 5
, #Sql nvarchar(MAX)
, #Table sysname = 'Table'
, #Name nvarchar(MAX) = N'Name';
SET #Sql = N'SELECT #totalCount = COUNT(*) + #Qty
FROM ' + QUOTENAME(#Table) + ' where [Name] = #Name;';
EXEC sp_executesql
#Sql
, N'#Name nvarchar(MAX), #Qty int, #totalCount int OUTPUT'
, #Name = #Name
, #Qty = #Qty
, #totalCount = #totalCount OUT;

PRINT not print the dynamic sql

declare #sImport_Table1 table
(
Id int identity(1,1) ,
Zone nvarchar(50),
Sub_Code nvarchar(50),
Geography nvarchar(50),
DayOfWeek nvarchar(50)
)
INSERT INTO #sImport_Table1 SELECT 'A','Z','Geo','SUN'
declare #sZone nvarchar(50)
declare #sSubCode nvarchar(50)
declare #c_Geography nvarchar(50)='Geo'
declare #c_DayOfWeek nvarchar(50)='SUN'
declare #sImport_Table nvarchar(500)='#sImport_Table1'
--SELECT * FROM #sImport_Table1
declare #sQuery nvarchar(4000)
SET #sQuery='SELECT '+ #sZone + ' = Zone,'+
#sSubCode +' = Sub_Code
FROM'+ #sImport_Table +
' WHERE Geography ='+ #c_Geography +
' AND DayOfWeek = '+ #c_DayOfWeek
PRINT #sQuery
*************** EDITED********************************
declare #sImport_Table1 table
(
Id int identity(1,1) ,
Zone nvarchar(50),
Sub_Code nvarchar(50),
Geography nvarchar(50),
DayOfWeek nvarchar(50)
)
INSERT INTO #sImport_Table1 SELECT 'A','Z','Geo','SUN'
declare #sZone nvarchar(50)
declare #sSubCode nvarchar(50)
declare #c_Geography nvarchar(50)='Geo'
declare #c_DayOfWeek nvarchar(50)='SUN'
declare #sImport_Table nvarchar(500)='#sImport_Table1'
--SELECT * FROM #sImport_Table1
declare #sQuery nvarchar(4000)
SET #sQuery='''SELECT #sZone = Zone, '+
'#sSubCode = Sub_Code
FROM '+ #sImport_Table +
' WHERE Geography ='''+ #c_Geography + '''
AND [DayOfWeek] = '''+ #c_DayOfWeek +''''''
PRINT #sQuery
sp_executesql #sQuery
PRINT #sZone
PRINT #sSubCode
You have #sZone and #sSubCode which are null. Concatenation with null is always null.
This can make sense.
SET #sQuery='SELECT #sZone = Zone, '+
'#sSubCode = Sub_Code
FROM '+ #sImport_Table +
' WHERE Geography ='+ #c_Geography +
' AND [DayOfWeek] = '+ #c_DayOfWeek
Notice, that the DayOfWeek is reserved word and must be included in square bracket.

How to use Pass comma separated string in dynamic query in SQL

I have a function which will return integer values from comma delimited string , It takes two parameters (#string nvarchar(4000), #delimiter char(1)). So the problem is if I am using this function inside a dynamic query I am getting error , here is query
declare #ProductIDs varchar(11)
declare #SQL varchar(max)
set #ProductIDs='1,2,3,4'
declare #query varchar(max)
--set #query= #ProductIDs +','+#Delimiter
SELECT #SQL = 'SELECT val FROM dbo.[fnDelimitedStringToTable]('+ #ProductIDs +' , '','')'
Exec(#SQL)
I am getting error Procedure or function dbo.fnDelimitedStringToTable has too many arguments specified.
When you build a dynamic SQL like that, you need to wrap your parameter in double quote ''
declare #ProductIDs varchar(11)
declare #SQL varchar(max)
set #ProductIDs='1,2,3,4'
declare #query varchar(max)
--set #query= #ProductIDs +','+#Delimiter
SELECT #SQL = 'SELECT val FROM dbo.[fnDelimitedStringToTable]('''+ #ProductIDs +''' , '','')'
Exec(#SQL)
This way the SQL statement will be:
SELECT val FROM dbo.[fnDelimitedStringToTable]('1,2,3,4' , '','')
and not:
SELECT val FROM dbo.[fnDelimitedStringToTable](1,2,3,4 , '','')
Use sp_executesql instead. In this case you can pass arguments as parameters.
DECLARE #SQL nvarchar(max)
DECLARE #ParmDef nvarchar(1000)
DECLARE #ArgProductIDs nvarchar(100)
DECLARE #Arg2 nvarchar(100)
DECLARE #Arg3 nvarchar(100)
SET #SQL = N'SELECT val
FROM dbo.[fnDelimitedStringToTable](#ProductIDs, #Param2, #Param3)';
SET #ParmDef = N'#ProductIDs nvarchar(100),
#Param2 nvarchar(100),
#Param3 nvarchar(100)';
SET #Arg1 = N'1,2,3,4';
SET #Arg2 = N'';
SET #Arg3 = N'';
EXEC sp_executesql #SQL, #ParmDef,
#ProductIDs = #ArgProductIDs, #Param2 = #Arg2, , #Param3 = #Arg3