SQL add a variable to a query - sql

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

Related

Passing a variable out of a SQL query

Is it possible to pass a variable out of a SQL query?
I am building up the initial query using a variable. I have added a simplified subset of my query below.
Thanks
declare #query Nvarchar(max)
declare #ColumnName Nvarchar(max)
set #ColumnName = 'MyColumn'
SET #query = 'Select ' + #ColumnName + ' from [MyTable] WHERE [MyCondition]'
EXECUTE sp_executesql #query
Can I return this result as a variable to pass to another query?
Yes. You use an output parameter:
declare #query Nvarchar(max);
declare #ColumnName Nvarchar(max);
declare #outval <type>; -- whatever type
set #ColumnName = 'MyColumn'
set #query = 'Select #outval =' + #ColumnName + ' from [MyTable] where [MyCondition]';
execut sp_executesql #query,
N'#outval <type> output',
#outval = #outval output;
Store the results in table variable and then convert it into XML.
Declare #xml XML
declare #query Nvarchar(max)
declare #ColumnName Nvarchar(max)
set #ColumnName = 'MyColumn'
declare #Table as TABLE(
MyColumn varchar(Max)-- Your Column datatype
)
SET #query = 'Select ' + #ColumnName + ' from [MyTable] WHERE [MyCondition]'
INSERT INTO #Table
EXECUTE sp_executesql #query
select #xml=MyColumn from #Table for XML PATH('')
How you want to pass returned result to other query?
What i can think of create a function return a table and call that function on other query:
CREATE FUNCTION test (#id int)
RETURNS #testTable TABLE(id int)
AS
begin
insert into #testTable select id from #your_table where id = #id
return
end
This will return a table you can check using :
select * from test(2); --will give you a table
If you want to use in a query:
`select * from #second_table where id in (select * from test2(#id parameter))` --- will filter query by id returned by function.

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.

Substitute Column name in dynamic queries

I have a procedure , in which i am receiving a parameter column name and creating the dynamic query by substituting column name.
when i am directly running this dynamic query its working fine.
declare #a datetime,
#b varchar(50) ='CREATED_DATE',--column name
#query varchar(500);
select #a= CONVERT(datetime,LAST_RUN_PROC,121) from TEST_TABLE_MASTER
exec( 'select '+#b+' from TEST1 where '+#b+' = '+''''+#a+'''' )
But when i am storing query in a variable and then executing,its showing error.
Below code showing error
declare #a datetime,
#b varchar(50) ='CREATED_DATE',--column name
#query varchar(500);
select #a= CONVERT(datetime,LAST_RUN_PROC,121) from TEST_TABLE_MASTER
SET #query= 'select '+#b+' from TEST1 where '+#b+' = '+''''+#a+'''' --this line showing error Conversion failed when converting date and/or time from character string.
exec (#query)
I got stuck here.please help
Concatenating SQL string is not the best idea, because of multiple '''' needed. It is error-prone and hard to debug.
Use correct types (table name, column name) - SYSNAME, query -NVARCHAR(MAX).
You can use REPLACE placeholder to fill values or pass them as parameter to EXEC dbo.sp_executesql.
Always quote table/column names.
SELECT #a= CONVERT(datetime, LAST_RUN_PROC,121) FROM TEST_TABLE_MASTER; will set #a last read value from table, you should add TOP 1 and ORDER BY.
Code:
DECLARE #a DATETIME,
#b SYSNAME ='CREATED_DATE',
#query NVARCHAR(MAX);
SELECT #a= CONVERT(datetime, LAST_RUN_PROC,121) FROM TEST_TABLE_MASTER;
SET #query =
N'SELECT <col_name>
FROM TEST1
WHERE <col_name> = ''<col_value>'';';
SET #query = REPLACE(#query, '<col_name>', QUOTENAME(#b));
SET #query = REPLACE(#query, '<col_value>', #a);
--SELECT #query;
EXEC [dbo].[sp_executesql]
#query;
SqlFiddleDemo
Recommended version with parameter passing and dbo.sp_executesql instead of EXEC:
DECLARE #a DATETIME,
#b SYSNAME ='CREATED_DATE',
#query NVARCHAR(MAX);
SELECT #a= LAST_RUN_PROC FROM TEST_TABLE_MASTER;
SET #query =
N'SELECT <col_name>
FROM TEST1
WHERE <col_name> = #a;';
SET #query = REPLACE(#query, '<col_name>', QUOTENAME(#b));
EXEC [dbo].[sp_executesql]
#query
,N'#a DATETIME'
,#a;
SqlFiddleDemo2
Warning:
Using Dynamic-SQL is great resposibility. If you don't understand it, don't use Dynamic-SQL at all.
EDIT:
I've managed to run your example, but I strongly recommend to use one of the solution above:
SET #query= 'select '+#b+' from TEST1 where '+#b+' = '+''''+CONVERT(varchar(19),#a, 121)+''''
SqlFiddleDemo3

How to store results of dynamic SQL into a variable

is there a way to store the results of an exec statement in a varchar?
DECLARE #TableName varchar(100)
DECLARE #ExecStatement varchar(max)
DECLARE #PromotionXML varchar(max)
SET #TableName = 'Feeds'
Set #ExecStatement = (
'
SET #PromotionXML = (
SELECT
*
FROM
' + #TableName + ' for xml auto, elements
)'
)
exec #ExecStatement
select #PromotionXML
You need to use sp_executesql, not EXEC, since you need to treat the inner variable as an output parameter (which you can't do with EXEC). Also all of these parameters should be NVARCHAR, not VARCHAR (though I'm curious why you aren't returning the xml as XML).
DECLARE
#TableName NVARCHAR(512),
#sql NVARCHAR(MAX),
#xml NVARCHAR(MAX);
SET #TableName = N'dbo.Feeds';
SET #sql = N'SELECT #xml = CONVERT(NVARCHAR(MAX), (
SELECT * FROM ' + #TableName + ' FOR XML AUTO, ELEMENTS));';
EXEC sp_executesql #sql, N'#xml NVARCHAR(MAX) OUTPUT', #xml OUTPUT;
SELECT #xml;

Dynamic sql statement to update a variable

my sql statement is something like this below
DECLARE #OLD_NAV_VALUE AS INT
DECLARE #FINAL AS INT
SELECT #OLD_NAV_VALUE = [col1] from TBL_BA where DATE = #id_Date
SET #FINAL = #OLD_NAV_VALUE * 50
But the problem i am haveing here is that the column name in the select statement which is given as [col1] is a dynamic value. So i am trying something like this below.
DECLARE #OLD_NAV_VALUE AS INT
DECLARE #FINAL AS INT
EXEC('SELECT #OLD_NAV_VALUE = [' + #DYNAMIC_COL_NAME + '] from TBL_BA where DATE = ' + #id_Date)
SET #FINAL = #OLD_NAV_VALUE * 50
this gives an error that #OLD_NAV_VALUE has to be declared. So i tried declaring #OLD_NAV_VALUE inside the EXEC statement. But if i do this i am not able to use the same outside the EXEC statement.
Please let me know how to do this.
You can also use the sp_executesql statement with an output parameter:
declare #field nvarchar(50);
set #field = N'FieldToSelect';
declare #sql nvarchar(3000);
declare #parmDefinition nvarchar(500);
SET #parmDefinition = N'#returnValueOUT nvarchar(50) OUTPUT';
set #sql = N'SELECT #ReturnValueOUT = ' + #Field + ' FROM [TableName] WHERE [SomeCondition]'
declare #returnValue nvarchar(50);
EXECUTE sp_executesql #sql, #parmDefinition, #returnValueOut = #returnValue OUTPUT;
SELECT #returnValue
First, I'd suggest that you do a Google on "Erland dynamic SQL" and read his white paper on the subject.
Your design is probably not the best if it requires that you use a dynamic column name like this.
The reason that you can't do what you're trying to do is that everything in the EXEC is entirely in its own scope. If you absolutely have to do it this way though then you could use a table (either a normal table, or a global temporary table) to store the value for use outside of the EXEC.
We've used sp_executesql. Here's another example of a parameterized record count:
DECLARE #sql AS nvarchar(MAX)
SET #sql = N'SELECT #RecordCount = COUNT(*) FROM [{#SchemaName}].[{#TableName}]'
SET #sql = REPLACE(#sql, '{#SchemaName}', #SchemaName)
SET #sql = REPLACE(#sql, '{#TableName}', #TableName)
DECLARE #RecordCount AS int
EXEC sp_executesql
#query = #sql,
#params = N'#RecordCount INT OUTPUT',
#RecordCount = #RecordCount OUTPUT
This worked for me.
I declared a temp table and used it to receive the values from the select statement.
Something like below.
declare #i int
declare #v int
create table #t (val int)
insert into #t
exec ('declare #i int set #i = 0 select #i+1')
select * from #t