Get a value of a variable dynamically in SQL Server SP - sql

Is there a way to get a value of a local variable specified by its name dynamically in SQL Server SP?
declare #foo int
declare #bar int
declare #variable_name varchar(10)
set #variable_name = '#foo'
print -- magic happens here - how to print the value of the variable
-- which name is stored in #variable_name, in this case #foo
eval won't help since it does not have access to local variables of the enclosing scope.
I'm doing this for debugging/diagnostics purposes mostly.

Technically this is possible by passing all local variables to sp_executesql:
declare #foo int
declare #bar int
declare #variable_name varchar(10)
set #variable_name = '#foo'
set #foo = 1;
set #bar = 2;
declare #sql nvarchar(max);
set #sql = N'SELECT ' + #variable_name;
exec sp_executesql #sql, N'#foo int, #bar int', #foo, #bar
Of course this would be quite hard to maintain in real life, the call to sp_executesql would have to be constantly kept up to date with the local variables on the current frame (batch or procedure call). While this is somewhat 'generic', is hardly any better than using a big CASE with all local variable names.

AFAIK, no: there is no direct way of doing this on SQL Server.

declare #foo int
declare #bar int
select #foo=1, #bar=2
declare #variable_name varchar(10)
set #variable_name = '#foo'
if #variable_name = '#foo'
print #foo
else if #variable_name = '#bar'
print #bar

Related

Problem with a dynamic function in SQL Server

I have a table dbo.t_products and I want to know the last record updated. For that I have an attribute last_changed which stores for each record the timestamp of the last update.
Finally I want to save that result in a variable called #y.
DECLARE #y DATETIME
DECLARE #p_table VARCHAR(100)
SET #p_table = 'dbo.t_products'
EXECUTE sp_executesql N'SET #y = SELECT MAX(last_changed) FROM #p_table'
,N'#p_table VARCHAR, #y DATETIME OUTPUT'
,#p_table
,#y OUTPUT
SELECT #y
The system returns the following message:
Msg 156, Level 15, State 1, Line 25
Incorrect syntax near the keyword 'SELECT'.
Any ideas?
The whole point of using dynamic SQL in your case (I assume) is to allow the use of a dynamic table name. In which case you have to insert the table name into the dynamic SQL string - you can't pass it in as a parameter, thats the problem you are trying in the first place.
Also you don't need a SET followed by a SELECT just use SELECT directly to set the variable.
Finally you definitely want to use the QUOTENAME function to escape your table name and avoid an SQL injection attack - this requires you split the table name and schema name.
DECLARE #y DATETIME;
DECLARE #p_schema VARCHAR(100);
DECLARE #p_table VARCHAR(100);
DECLARE #SQL NVARCHAR(max);
SET #p_schema = 'dbo';
SET #p_table = 't_products';
-- Add the table name to the dynamic SQL
SET #SQL = 'SELECT #y = MAX(last_changed) FROM ' + QUOTENAME(#p_schema) + '.' + QUOTENAME(#p_table);
EXECUTE sp_executesql #SQL, N'#y DATETIME OUTPUT', #y OUTPUT;
-- PRINT(#SQL); --- Debugging
SELECT #y;

MS SQL - Variable in a variable

I've been wondering if it's possible to declare and set a variable within the definition of another variable.
For example:
declare #variable varchar(250)
set #variable =
'INSERT INTO [BLAH] (Nope, Hype, Friends)
VALUES (declare #value varchar(250) set #value = 'example' exec #value, #value, #value)'
exec #variable
I'm probably doing multiple really basic mistakes here - just trying to understand as much as fast as possible
it can be done as below.
declare #variable varchar(800)
set #variable =
' declare #value varchar(10) = ''example''
INSERT INTO [BLAH] (Nope, Hype, Friends)
VALUES ( #value, #value, #value)'
exec #variable
Also get a knowledge of SQL injection before you work with dynamic sql.
Yes you can declare a set of variable inside a variable: doing like this.
DECLARE #variable varchar(max)
SET #variable =
'declare #value varchar(max) = ''example''
Insert into BLAH
values(#value,#value)'
EXEC (#variable)
Here we simply declared a variable #value inside another variable #variable

Execute Stored Procedure from Stored Procedure w/ dynamic SQL capturing output

Inside a stored procedure (A) I need to call a stored procedure (X) inside a specific database and capture the output. X returns a single value.
From what I understand I need to provide the DB name of X to the stored procedure in A and I need to use dynamic SQL to build the query on execution targeting the desired database.
What am unable to figure out is how to capture output from X in A to work with the result.
You could use sp_executesql to dynamically call your nested Stored Procedure.
DECLARE #db AS SYSNAME
DECLARE #return_value AS INT
DECLARE #output_value AS INT
DECLARE #sql AS NVARCHAR(MAX)
-- Set your DB name
SET #db = N'mydb'
/*
Use sp_executesql to dynamically pass in the db and stored procedure
to execute while also defining the values and assigning to local variables.
*/
SET #sql = N'EXEC #rtn = ' + #db + '.dbo.[your_stored_procedure] #output OUTPUT'
EXEC sp_executesql #sql
, N'#rtn AS INT, #output AS INT OUTPUT'
, #return_value = #rtn
, #output_value = #output OUTPUT
Adding to the above answer, following is the way to call stored procedures dynamically by passing parameters.
DECLARE #SpName VARCHAR(1000)
SELECT #SpName = DeleteLiveSP FROM dbo.ArchivalInfo (NOLOCK) WHERE TableName = #TableName
DECLARE #SqlString nvarchar(2000)
DECLARE #ParamDef nvarchar(2000)
SET #SqlString = N'exec '+#SpName + ' #CriteriaParam'
SET #ParamDef = N'#CriteriaParam XML'
EXECUTE sp_executesql #SqlString ,#ParamDef, #CriteriaParam = #Criteria

Sql: Script to substitute stored procedure calls with stored procedure code

I'd like at tool/script that would automatically substitute the calls to stored procedures with the code. It is better to explain with an example.
I have a code like this where a stored procedure is called twice
declare #x int, #y int
set #x = 10
exec #y = calculate_and_insert #x
set #x = #y
exec #y = calculate_and_insert #x
the called procedure has a code like:
create stored procedure calculate and insert #in int
as
declare #x int
set #x = 10
return #x + #in
See that it has a variable with the same name of one in the outer scope
I'd like to generate something like:
declare #x int, #y int
set #x = 10
declare #cai1_in int
set #cai1_in = #x
declare #cai1_x int
set #cai1_x = 10
set #y = #cai1_x + #cai1_in
set #x = #y
declare #cai2_in int
set #cai2_in = #x
declare #cai2_x int
set #cai2_x = 10
set #y = #cai2_x + #cai2_in
Maybe somebody already needed to do something like it. The reasoning is that I have a lot of stored procedures that I don't want to change in production, but I'd like to execute a new version of them to see the result. I'd recode them in test and generate a script.
I don't have to be done through SQL, can be done in another language. It also don't have to cover all cases.
Why don't you create a new stored procedure called calculate_and_insert2 and just alter your script to call the new procedure. That will be a lot less error-prone than your initial suggestion.

Must declare the scalar variable error SQL

I have this SQL statement, but i have error Must declare the scalar variable "#InputPath"
IF OBJECT_ID('DBO.SP_INSERT_REQUESTS') IS NULL BEGIN
EXEC('CREATE PROCEDURE DBO.SP_INSERT_REQUESTS AS RETURN')
GRANT EXECUTE ON DBO.SP_INSERT_REQUESTS TO PUBLIC
END
GO
ALTER PROCEDURE DBO.SP_INSERT_REQUESTS
#Name NVARCHAR(512),
#Code NVARCHAR(50),
#InputPath NVARCHAR(2000),
#OutputPath NVARCHAR(2000)
AS
GO
SET QUOTED_IDENTIFIER OFF
--DECLARE #InputPath varchar(2000) = "c:\MyDoc1.xsd"
DECLARE #InputValue XML
--DECLARE #OutputPath varchar(2000) = "c:\MyDoc2.xsd"
DECLARE #OutputValue XML
DECLARE #QUERY NVARCHAR(4000) SET #QUERY = "
SELECT #InputValue = InputExample.BulkColumn
FROM OPENROWSET (BULK '"+#InputPath+"', SINGLE_BLOB) AS InputExample;
SELECT #OutputValue = InputExample.BulkColumn
FROM OPENROWSET (BULK '"+#OutputPath+"', SINGLE_BLOB) AS InputExample;
"
EXEC SP_EXECUTESQL #QUERY, N'#InputValue XML out, #OutputValue XML out', #InputValue out, #OutputValue out
INSERT INTO MyTable(Name, Code, Input, Output)
VALUES('value1', 'value2' , #InputValue, #OutputValue)
I have declared the parameters, so I don't understand why I am getting the error.
Remove the GO which is between 'AS' and 'SET QUOTED_IDENTIFIER OFF'. The problem is that you declare the variable in a different batch.
Dynamic sql runs in a different session and therefore variables defined outside the dynamic query will not be available to the dynamic query DEMO - HERE.
Then again, if you declare them within the dynamic query, they won't be available outside the query. DEMO - HERE
I can see why you using dynamic sql as you cannot pass parameter to openrowset. I think you could do something like this to over come the issue. DEMO