Assigning a scalar variable from sp_executesql - sql

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.

Related

Error in dynamic execute with local variable

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.

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 ('')
)
';

Stored procedure to Linked server with parameters - Error

I'm trying to create stored procedure to Linked server, which input parameter #ServerName is the name of Linked Server i use.
In this procedure I also Declare parameter which value I want to get from Dynamic SQL Query and line.
CREATE PROC sp_Version #ServerName varchar(30)
as
Declare #Ver varchar(10)
exec ('select #Ver from openquery(' + #ServerName + ', ''SELECT SUBSTRING (##VERSION, 22, 7) = #Ver''')
When I execute my sp i get an error saying:
"Must declare the scalar variable "#Ver"."
Could you please help me?
I'm not sure what your aim is with the value of #Ver, perhaps an OUTPUT parameter? If so, then the syntax would be:
CREATE PROC GetVersion #ServerName varchar(30), #Ver nvarchar(500) OUTPUT AS
DECLARE #SQL nvarchar(MAX);
SET #SQL = N'SELECT #dVer = Version' + NCHAR(10) +
N'FROM OPENROWSET(''SQLNCLI'',' + NCHAR(10) +
N' ' + QUOTENAME('Server=' + #ServerName + ';Trusted_Connection=YES;','''') + ',' +NCHAR(10) +
N' ''SELECT ##VERSION AS Version'');';
PRINT #SQL;
EXEC sp_executesql #SQL, N'#dVer nvarchar(500) OUTPUT', #dVer = #Ver OUTPUT;
GO
DECLARE #ver varchar(500)
EXEC GetVersion 'YourServerName', #ver OUTPUT;
PRINT #ver;
GO
DROP PROC GetVersion;
Note, firstly, as suggested I didn't use the sp_ prefix. I've also used sp_executesql instead of simply EXEC (this is generally better practice, as you can parametrise your dynamic SQL then, as i have done), and QUOTENAME to try and avoid injection.
I have come across this situation a couple of times. Try this:
CREATE PROC sp_Version #ServerName varchar(30)
as
Declare #Ver varchar(10)
DECLARE #SqlCommand nvarchar(MAX)
SET #SqlCommand = 'SELECT #Ver2 = SUBSTRING (##VERSION, 22, 7) '
DECLARE #sp_executesql VARCHAR(100)
SET #sp_executesql = #ServerName + '.master.sys.sp_executesql'
EXEC #sp_executesql #SqlCommand, N'#Ver2 nvarchar(10) out', #Ver out
SELECT #Ver

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 do I query a value dynamically in T-SQL?

For whatever reason, I can't seem to get a value out dynamically from SQL.
declare #SQL nvarchar(max)
declare #FieldName nvarchar(255)
declare #FieldValue nvarchar(max)
select #SQL = 'SELECT TOP 1 ' + #fieldname
+' FROM MyTable WHERE CM_CASE_YEAR = ' + LEFT(#ClaimNumber, 2)
+' AND CM_CASE_NUMBER = ' + RIGHT(#ClaimNumber, 6)
exec sp_executesql #sql, #FieldValue OUTPUT
select #FieldName + ' - ' + #FieldValue
When I run the #SQL query in another window, it displays one column with one value.
But, unfortunately when I try this, #FieldValue always comes back NULL.
Did I miss something the day they taught sp_executesql? Obviously! But what?
See this example
DECLARE #SQL NVARCHAR(MAX)
DECLARE #FieldName sysname = 'name'
DECLARE #FieldValue NVARCHAR(MAX)
SELECT #SQL = 'SELECT TOP 1
#FieldValue =' + QUOTENAME(#FieldName) + ' FROM sys.objects'
EXEC sp_executesql #SQL,
N'#FieldValue nvarchar(max) OUTPUT',
#FieldValue =#FieldValue OUTPUT
SELECT #FieldName + ' - ' + #FieldValue
sp_executesql returns (generates) a resultset. #FieldValue is meaningless in the code above - sp_executesql won't put any value into that variable.