Error in dynamic execute with local variable - sql

I'm getting the error :
Procedure expects parameter '#params' of type 'ntext/nchar/nvarchar'
for the following execute statement. I'm a little confused with this, after reading several posts on the website,
I came to understand that I would need to pass #val as a variable since exec will execute the command as-is.
declare #val varchar(max);
declare #query nvarchar(max);
set #query = 'set #val = (select ' + #cols + ' from temp where loan_number = ''72'')'
exec sp_executesql #query, '#val varchar(max) output', #val output
Conversely, if I executed the exec as a non-dynamic query as just exec(#query), I get the error
Must declare the scalar variable "#val".

IF the statement "Should the output of the query be a 1x1 table since I" is true, then you need to use a SELECT to set the value:
DECLARE #val varchar(MAX);
DECALRE #query nvarchar(MAX);
SET #query = N'SELECT #val = ' + QUOTENAME(#cols) + N' FROM temp WHERE loan_number = ''72'');';
EXEC sp_executesql #query, N'#val varchar(MAX) OUTPUT', #val OUTPUT;
The fact that you have a variable called #cols implies that the variable will hold the names of many columns, not one.

Related

Concatenation problem in Dynamic sql query

I'm trying to concatenate the string with multiple variables and go for exec. Unfortunately I'm facing the conversion problem as:
Conversion failed when converting the varchar value 'Select #ExistingIds= CBSE_IX_J from ##tempPivot where EmployeeID=' to data type int.
My query is :
SET #ExecColumn = concat('Select #ExistingIds= '+#TSectionName +' from ##tempPivot where EmployeeID='+CAST(#TUserID as INT),'')
PRINT #ExecColumn
EXEC (#ExecColumn)
The "simple" answer is don't concatenate raw string values into your dynamic statement, and parametrise your code. This is a bit of guesswork, however, is far safer than the SQL Injection hole you have right now:
DECLARE #SQL nvarchar(MAX);
SET #SQL = N'SELECT #ExistingIDs = ' + QUOTENAME(#TSectionName) + NCHAR(13) + NCHAR(10)+
N'FROM ##tempPivot' + NCHAR(13) + NCHAR(10) +
N'WHERE EmployeeID = #TUserID;';
PRINT #SQL;
EXEC sp_executesql #SQL,
N'#TUserID int, #ExistingIds int OUTPUT', --guessed datatypes and that #ExistingIds is an OUTPUT
#TUserID = #TUserID,
#ExistingIds = ExistingIds OUTPUT;
Note: the fact that your variable is called #ExistingIDs implies you want to store multiple values in that variable. #ExistingIDs is a scalar value, it will only hold a scalar (single) value. If the query above returns multiple rows, only the value of from the last row will be returned. For example:
DECLARE #i int;
SELECT #i = I
FROM (VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9))V(I)
ORDER BY I;
SELECT #i;
Notice that #i has the value 9, not '1,2,3,...,9'.
You would seem to want:
DECLARE #SQL nvarchar(MAX);
DECALRE #ExistingIds NVARCHAR(MAX);
SET #SQL = N'
SELECT #ExistingIDs = STRING_AGG(#TSectionName, '''')
FROM ##tempPivot
WHERE EmployeeID = #TUserID
';
-- Cannot have identifiers as parameters, so use `REPLACE()`
SET #SQL = REPLACE(#SQL, '#TSectionName', QUOTENAME(#TSectionName);
EXEC sp_executesql #SQL,
N'#TUserID int, #ExistingIds NVARCHAR(MAX) OUTPUT', --guessed datatypes and that #ExistingIds is an OUTPUT
#TUserID=#TUserID,
#ExistingIds=#ExistingIds OUTPUT;
In older versions of SQL Server, you need another approach for concatenating strings. For instance
SET #SQL = N'
SELECT #ExistingIDs = (SELECT #TSectionName
FROM ##tempPivot
WHERE EmployeeID = #TUserID
FOR XML PATH ('')
)
';

Assigning a scalar variable from sp_executesql

I need anyone's help. I am trying to assign a scalar variable from a query, running from sp_executesql. my query is below:
select #sql = N'Select #found = count(' +#column+ ') from ' +#table+ ' where
+#column+ ' = ''' +#intVariable+''';';
EXECUTE sp_executesql #sql, N'#table nvarchar(max), #column nvarchar(max),
#temp_id nvarchar(max), #found int',
#table,#column,#temp_id,#found;
The query does not yield any errors. but #found was not assigned the result of the query. I tried to change to set but also the same. can anyone please tell me what is wrong with the query? I have been doing this for all day long.
Thanks so much in advance for all the help i can get.
Your script would look as follows:
DECLARE #found int;
DECLARE #sql NVARCHAR(MAX) =
N'Select #found = count(' +QUOTENAME(#column)+ ') '+
N'from ' +QUOTENAME(#table)+ ' '+
N'where ' +QUOTENAME(#column)+ '=#intVariable;';
EXEC sp_executesql #sql, '#intVariable INT, #found INT OUTPUT', #intVariable, #found OUTPUT;
This has #found as an OUTPUT variable. It is necessary to specify this both in the parameter string and when passing the parameter to sp_executesql to output the value.
Also, QUOTENAME() is used to properly escape object names.

SQL add a variable to a query

How do I create variables that are specified once and then used in queries later in a script? These variables may be used multiple times in a query, and in multiple queries in a script. I use #x as such a variable in the examples below.
What I want to do is something like:
Declare #Query nvarchar(1000)
Declare #x nvarchar(40)
Set #x = 'test'
Set #Query = 'Select [Name]
, ' + #x + ' as [TestCase]
From mytable'
Exec (#Query)
-- returns "Invalid column name 'test'"
Which returns the error mentioned above. I would like it to achieve the equivalent of:
Declare #Query nvarchar(1000)
Declare #x nvarchar(40)
Set #x = 'test'
Set #Query = 'Select [Name]
, ''test'' as [TestCase]
From mytable'
Exec (#Query)
-- Returns e.g.
-- Name TestCase
-- Alice Test
-- Bob Test
I also note that the following doesn't work and returns the same error as the first:
Declare #Query nvarchar(1000)
Declare #x nvarchar(40)
Set #x = 'test'
Set #Query = 'Select [Name]
, ' + 'test' + ' as [TestCase]
From mytable'
Exec (#Query)
-- returns "Invalid column name 'test'"
Based on the error and since I'm not trying to use the #x as a column name, but just as a variable, I assume I'm using an invalid implementation of a variable.
Since you're not trying to use a variable as a column name, you do not need to use dynamic SQL at all. (Which is a Good Thing(TM) since dynamic SQL should only be used with a great deal of caution due to it being a great attack surface.)
A simple:
declare #x nvarchar(40)
set #x = 'test'
select [Name], #x as TestCase
from mytable
will do.
That being said, if you have a use case for dynamic SQL (again the particular query in question here does not but perhaps an ad-hoc query is being passed in to the procedure), the thing to do would be to pass your variable as a parameter to the query via sp_executesql. This is akin to creating a stored procedure with parameters:
declare #x nvarchar(40)
declare #query nvarchar(1000)
set #x = 'test'
set #query = 'select [Name], #x as TestCase from mytable'
exec sp_executesql #query, N'#x nvarchar(1000)', #x
You were missing quotes. Thats it. Try below code.
Declare #Query nvarchar(1000)
Declare #x nvarchar(40)
Set #x = 'test'
Set #Query = 'Select [Name]
, ''' + #x + ''' as [TestCase]
From mytable'
Exec (#Query)
Declare #Query nvarchar(1000)
Declare #x nvarchar(40)
Set #x = 'test'
Set #Query = 'Select [Name],'++''''+#x+''''+ ' as [TestCase]
From mytable'
print #query
Output:
Select [Name],'test' as [TestCase]
From mytable

SQL Linked Server query with Parameters

I need to select value from SQL Linked Server & get it to loacal variable
This is what I've written so far:
DECLARE #SQLQUERY AS VARCHAR(1000)
DECLARE #FINALQUERY AS VARCHAR(1000)
DECLARE #OutVal AS VARCHAR(10)
SET #SQLQUERY = 'SELECT Field1 FROM Table1 WHERE Field2=' + CAST(#var1 AS VARCHAR)
SET #FINALQUERY = 'SELECT #OutVal=Field1 FROM OPENQUERY(LINKEDSERVER,' + '''' + #SQLQUERY + '''' + ')'
EXEC(#finalQuery)
but this is wrong as it does not set the local variable(#OutVal).
Instead of exec, use sp_execute_sql with an output parameter:
exec sp_executesql #FinalQuery, N'#OutVal output', #OutVal = #OutVal out
Since sp_executesql expects nvarchar parameters, be sure to change the definition of #FinalQuery to nvarchar(max).
#OutVal in query string does not recognized as a variable. use a function or return table statement.

how to pass variables this in dynamic query in sql

i using the dynamic query to pass the variables
select a.TableName, COUNT(a.columnvalue) as '+'count'+' from Settings a
where a.ColumnValue in ('+ #columnvalue +') and a.Value in (' + #value +')
the #columnvalues = 'a','b','c'
#value ='comm(,)','con(:)'
how to pass this in dynamic query
any idea???
I would use the sp_executesql command.
Some more documentation is here: http://msdn.microsoft.com/en-us/library/ms188001.aspx
Basically, you define a sql query, and parameter list, and then pass those in along with your actual parameters into that method.
So, something like this (real basic)
CREATE PROCEDURE dbo.yourProc
#customerId INT
AS
DECLARE #sql NVARCHAR(1000)
SET #sql = 'SELECT * FROM Customers WHERE CustomerId = #customerId'
DECLARE #params NVARCHAR(1000)
SET #params = '#customerId INT'
EXEC dbo.sp_executesql #sql, #params, #customerId