cannot transfer value from a variable to another variable - sql

I have a problem when I would like to transfer the value of a variable to another variable.
declare #column varchar(255);
set #column = 'cheesecake';
declare #tmp varchar(255);
set #tmp = (select #column from TEST where id = 1);
But in this case #tmp won't have the value of the table, but the name of the #column variable. I tried it with dynamic sql, but I got a syntax error.
declare #column varchar(255);
set #column = 'cheesecake';
declare #tmp varchar(255);
set #tmp = exec('select ' + #column + ' from TEST where id = 1');
How can I solve that the #tmp variable would contain the value of the query?

EXEC executes in a different context, therefore the variables cannot be shared without hassle. You specify an output parameter to the statement using sp_executesql
DECLARE
#language nvarchar(255),
#translation nvarchar(255),
#statement nvarchar(255)
SET #language = N'norwegian'
SET #statement = 'select #translation='+#language+' from Translations where id = 1'
EXEC sp_executesql
#statement,
N'#translation nvarchar(255) OUTPUT',
#translation OUTPUT
SELECT #translation
SQLFiddle

AFAIK, it is not possible to directly assign to a variable using `exec. A workaround to your issue would be to create a table variable to store the results of the dynamic query, and then set the value of the second variable using the table variable, like so:
declare #column varchar(255);
set #column = 'cheesecake';
declare #tmp varchar(255);
declare #query nvarchar(255) = N'select ' + #column + N' from TEST where id = 1'
declare #tbl table(tmp varchar(255)) --Intermediate Table variable
insert into #tbl --Insert dynamic query results here
exec sp_executesql #query
select top 1 #tmp = tmp from #tbl --Assign value here
select #tmp
EDIT: I stand corrected. This answer shows how you can assign from dynamic SQL result to a variable by making use of OUTPUT parameters within the dynamic query.

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.

Dynamic SQL output of a query to a variable

I would like to output the result of the dynamic SQL into a variable called #Count but not sure what the syntax or even the code should like to accomplish this.
The code looks as follows:
declare #tab nvarchar(255) = 'Person.person'
declare #Count int
declare #SQL nvarchar(max) = 'select count(*) from '+ #tab
exec(#SQl)
select #Count
thank you
Here's another way to do it that also safely addresses the SQL Injection isuues:
/* Counts the number of rows from any non-system Table, *SAFELY* */
-- The table name passed
DECLARE #PassedTableName as NVarchar(255) = 'Person.Person';
-- Make sure this isn't a SQL Injection attempt
DECLARE #ActualTableName AS NVarchar(255)
SELECT #ActualTableName = TABLE_SCHEMA + '.' + TABLE_NAME
FROM INFORMATION_SCHEMA.TABLES
WHERE TABLE_NAME = PARSENAME(#PassedTableName,1)
AND TABLE_SCHEMA = PARSENAME(#PassedTableName,2)
-- make a temp table to hold the results
CREATE TABLE #tmp( cnt INT );
-- create the dynamic SQL
DECLARE #sql AS NVARCHAR(MAX)
SELECT #sql = 'SELECT COUNT(*) FROM ' + #ActualTableName + ';'
-- execute it and store the output into the temp table
INSERT INTO #tmp( cnt )
EXEC(#SQL);
-- Now, finally, we can get it into a local variable
DECLARE #result AS INT;
SELECT #result = cnt FROM #tmp;
You can utilize sp_executesql to execute your count() query, and output it #Count.
Try this:
-- Set the table to count from
declare #tab nvarchar(255) = 'Person.person'
-- Assign the SQL query
declare #SQL nvarchar(255) = N'SELECT count(*) FROM ' + #tab
-- Pepare for sp_executesql
declare #Count int
declare #Params nvarchar(100) = N'#Count int output'
-- Set the count to #Count
exec sp_executesql #SQL, #Params, #Count=#Count output
-- Output #Count
select #Count
One last thing: Person.person looks like you might be trying to reference a person column from a Person table. But the above query is a literal representation of what it looks like you're trying to achieve in your question.
The below question is pretty much identical to what you are asking here.
sp_executeSql with output parameter
DECLARE #retval int
DECLARE #sSQL nvarchar(500);
DECLARE #ParmDefinition nvarchar(500);
DECLARE #tablename nvarchar(50)
SELECT #tablename = N'products'
SELECT #sSQL = N'SELECT #retvalOUT = MAX(ID) FROM ' + #tablename;
SET #ParmDefinition = N'#retvalOUT int OUTPUT';
EXEC sp_executesql #sSQL, #ParmDefinition, #retvalOUT=#retval OUTPUT;
SELECT #retval;

How to pass parameter value for a string that is inside Variable?

Can some one please help me how can I pass a Parameter value into a string that is inside a Variable
Ex:
DECLARE #STR VARCHAR(MAX) = ''
DECLARE #ID INT
SET #STR = 'SELECT * FROM STUDENT WHERE STUDENT_ID=#ID'
Here I want to pass #ID as a parameter to Variable #STR
Use sp_executesql to value to the parameter this will also avoid sql injection. Try this
DECLARE #STR NVARCHAR(MAX) = ''
DECLARE #ID INT
SET #STR = 'SELECT * FROM STUDENT WHERE STUDENT_ID=#ID'
exec sp_executesql #str,'#ID INT',#ID
Use this:
DECLARE #STR VARCHAR(MAX) = ''
DECLARE #ID INT
SET #STR = 'SELECT * FROM STUDENT WHERE STUDENT_ID=' + CAST(#ID AS VARCHAR(50))
Here's one easy way:
DECLARE #STR VARCHAR(MAX) = ''
DECLARE #ID INT
SET #STR = 'SELECT * FROM STUDENT WHERE STUDENT_ID=#ID'
SET #STR = REPLACE(#STR, '#ID', COALESCE(CAST(#ID AS varchar(31)),''))
And of course there are others. You could have used string concatenation when building #STR, or you could keep it the way it is and use a parameterized call to sp_executesql when you finally want to execute the string, assuming that's what you want to do with it.
You can write a query as:
DECLARE #ID int;
--to use sp_executesql sql statement must be a Unicode variable
DECLARE #STR nvarchar(500);
DECLARE #ParmDefinition nvarchar(500);
/* Build the SQL string.
as a best practice you should specify column names instead of writing *
*/
SET #STR =
N'SELECT Col1,Col2 FROM STUDENT WHERE STUDENT_ID=#ID';
SET #ParmDefinition = N'#ID Int';
/* Execute the string with the parameter value. */
SET #ID = 1;
EXECUTE sp_executesql #STR, #ParmDefinition,
#ID = #ID;
For simplicity you can also create a Store Procedure for it:-
Code in SQL
Create Proc [ProcedureName]
#ID As int
As
SELECT * FROM STUDENT WHERE STUDENT_ID=#ID
Calling a Store Procedure
[ProcedureName] 1
--Here replace "1" with your Id
DECLARE #STR VARCHAR(MAX) = ''
DECLARE #ID INT
SET #STR = 'SELECT * FROM STUDENT WHERE STUDENT_ID='+#ID
should do

SELECT FROM #random_table SQL Server 2008 R2

I'm having an issue with the following code:
DECLARE #table varchar(50), #value int
SET #table = 'randomTable'
EXEC('SELECT #value = exercicio FROM '+#table+' WHERE cod = 2')
I need to do a couple of operations like that one above in some random tables. I want to select a value and store in a variable previously declared. But when I tried to execute that code, I received the following message:
Must declare the scalar variable "#value".
I'm out of ideas. Any suggestions?
The #value variable is outside the scope of the dynamic SQL statement. You'll need to return the value as an output parameter:
DECLARE
#table nvarchar(251) = N'dbo.randomTable'
, #SQL nvarchar(MAX)
, #value int;
SET #SQL = N'SELECT #value = exercicio FROM '+#table+N' WHERE cod=2';
EXEC sp_executesql #SQL, N'#value int OUTPUT', #value OUT;

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