How to assign a value to variable using Sql String - sql-server

I would like to assign a select value to a variable using sql string. Below is my code:
DECLARE #maxRow INT, #tableName NVARCHAR(128) = N'whatever';
select #maxRow=Max(id) from #tableName
But this throws an error:
Msg 1087, Level 16, State 1, Line 3
Must declare the table variable "#tableName".
Even though I did declare the variable.

You can't use a variable for a table name unless you put it into dynamic SQL. The code is currently expecting #tableName to be a table variable, not a string, though it's clear from your syntax this is not what you intended. This usage smells like sub-optimal design and lends itself to significant SQL injection risks, but you can try this code instead:
DECLARE #maxRow INT;
DECLARE #sql NVARCHAR(MAX) = N'SELECT #maxRow = MAX(id) FROM '
+ QUOTENAME(#tableName) + ';';
EXEC sp_executesql #sql, N'#maxRow INT OUTPUT', #maxRow OUTPUT;
PRINT #maxRow;
Please do read up on SQL injection and normalization.

Related

Use numeric inside SQL statement in procedure

How to use numeric variable in sql statement inside procedure?
This is my try:
create procedure ##sp_check (
#tolerance numeric
)
AS
Declare #SQL nvarchar(max)
SET #SQL = '
SELECT
*
FROM
a
WHERE
value > #tolerance
'
exec sp_executesql #SQL
go
exec ##sp_check 1
and the ERROR: Must declare the scalar variable "#tolerance".
I think this is because the variable is invisible between ' and '
so I can do it by declaring #tolerance as varchar and in sql statement converting it into numeric but its a bit confusing...
You have to explicitly pass the variable into the sp_executesql (it runs in a different scope that doesn't have access to variables declared in the calling scope).
SET #SQL = 'SELECT * FROM a WHERE value > #t'
exec sp_executesql #SQL, N'#t numeric', #t=#tolerance
I wonder why you're using Dynamic SQL here.. try this:
create procedure ##sp_check (
#tolerance numeric
)
AS
SELECT * FROM a WHERE value > #tolerance
go
exec ##sp_check 1
You can't reference a variable declared outside of a dynamic statement inside it. Thus, the correct syntax would be:
CREATE PROC ##sp_check (#tolerance numeric)
AS
DECLARE #SQL nvarchar(max)
SET #SQL = N'SELECT *' + NCHAR(10) +
N'FROM a' + NCHAR(10) +
N'WHERE value > #dtolerance;';
PRINT #SQL;
EXEC sp_executesql #SQL, N'#dtolerance numeric',#dtolerance = #tolerance;
go
exec ##sp_check 1;
I suggest, however, you declare your scale and precision on your numeric, it's very bad practice to not do so.

sp_executesql with always true condition

i have been using dynamic queries in sql-server like:
declare #sql nvarchar (1000),#condition nvarchar(100)='';
set #sql=N'select * from tablename where (0=0)'+#condition+'';
exec(#sql)
by this i was able to get my result whether the #condition has any value or not.
But i got to know that sp_executesql is better then exec as it promote query plan reuse.
So, i tried my query with `sp_executesql,
set #sql =N'select * from dbo.testclient where (0=0) #condition'
exec sp_executesql #sql,N'#condition nvarchar(100)',#condition
but it failed with an error as
Incorrect syntax near '#condition'.
My problem is how can i make the above query to work with sp_executesql where the parameter #condition can be a condition or blank (' ') and what am i doing wrong.
When you use variables such as #condition in sp_executesql, it does not simply replace your variable in the sql string with the content of the variable.
What happens is that the variable is bound to the supplied value and the sql statement is untouched.
This all means that you need to create a full sql statement which uses variables if you want to leverage query plan reuse.
For example:
SET #byIDsql = 'select * from tableName where (0=0) and Id = #Id'
SET #byNameSQL = 'select * from tableName where (0=0) and FirstName = #FirstName'
Then you can use sp_executesql to supply the value of #id and #firstName and get query plan reuse.
exec sp_executesql #byIDsql, N'#ID INT', 15
Tested code,
DECLARE #Sql nvarchar(MAX)='',
#paramlist nvarchar(4000),
#id int=3
set #paramlist = N' #id1 int'
set #Sql='select * from test where id=#id1'
exec sp_executesql #Sql,#paramlist,#id
select #Sql

SQL Server 2012 error : Must declare the scalar variable #lcrcolumn_total

This is my first project in Dynamic SQL.
When i run the below query. I'm getting an error:
Must declare scalar variable "
Though i declared the variable #lcrcolumn_total upfront.
EXECUTE (' UPDATE facetswrk.dbo.ODS_SUBSC_PREM_REPORT ' + ' SET ' + #lcrcolumn_name + ' = #lcrcolumn_total')
Thanks in advance!!!
You need to pass variable to dynamic SQL:
DECLARE #sql NVARCHAR(MAX) =
'UPDATE facetswrk.dbo.ODS_SUBSC_PREM_REPORT
SET #lcrcolumn_name = #lcrcolumn_total'
-- WHERE = ?; -- are you sure you want to update all rows
SET #sql = REPLACE(#sql, '#lcrcolumn_name', QUOTENAME(#lcrcolumn_name));
EXEC dbo.sp_executesql
#sql,
N'#lcrcolumn_total INT', -- set type of #lcorumn_total
#lcrcolumn_total;
LiveDemo
Remarks:
Add WHERE condition otherwise you will update all rows
Use sp_executesql instead of EXEC
Pass variable #lcrcolumn_total with correct datatype
Use QUOTENAME to avoid SQL Injection, when replacing column_name
If you are learning dynamic SQL, then just learn to use sp_executesql, because it is the best way to execute such statement. It allows you to pass arguments in and out. This is important because the "exec" statement does not share variables with the outer context.
The code would look more like this:
DECLARE #sql nvarchar(max);
SET #sql = '
UPDATE facetswrk.dbo.ODS_SUBSC_PREM_REPORT
SET #lcrcolumn_name = #lcrcolumn_total
';
SET #sql = REPLACE(#sql, '#lcrcolumn_name', #lcrcolumn_name);
EXEC sp_executesql #sql, N'#lcrcolumn_total int', #lcrcolumn_total = #lcrcolumn_total;
Note that you cannot pass column and table names as parameters, so these are handled using REPLACE().

Create table by passing name as early defined and value assigned variable in SQL Server 2012 [duplicate]

This question already has answers here:
A table name as a variable
(10 answers)
Closed 7 years ago.
I was trying to create stored procedure for create table as below:
CREATE PROCEDURE tableCreation
AS
DECLARE #tableName NVARCHAR(30)
SET #tableName = 'Employee'
BEGIN
CREATE TABLE #tableName (
id INT NOT NULL
)
END
but when I execute the procedure, I get this error:
Msg 102, Level 15, State 1, Procedure tableCreation, Line 7
Incorrect syntax near '#tableName'.
What is the issue with above procedure or is there any other way to achieve above task?
You should build a string containing the SQL you need and then execute that string. This is known as dynamic SQL.
create procedure tableCreation
as
declare #tableName nvarchar(30)
begin
declare #Sql NVARCHAR(MAX) = 'create table ' + #tableName + '
(
id int not null
)'
EXEC(#Sql)
end
You need to ensure that you validate the value in the #tableName variable before it's passed in to avoid SQL injection attacks
http://www.troyhunt.com/2013/07/everything-you-wanted-to-know-about-sql.html
https://xkcd.com/327/
This might be something that will help, for starters:
create procedure tableCreation
as
declare #tableName nvarchar(30)
set #tableName = 'Employee'
begin
declare #sql nvarchar(max)
set #sql = 'CREATE TABLE ' + #tableName + '( id int not null )';
exec sp_executesql #sql
end
But there are better (but still not ideal) ways of using dynamic SQL, for example parametrizing your query which will decrease the changes of your code being prone to SQL Injection. Check out one of the established articles on this topic.
But, if you do not pass the table name as a parameter to the procedure, then I guess you're safe from SQL Injection (although this is some kind of obscure and strange behaviour).
CREATE PROCEDURE tableCreation
(
#tableName SYSNAME
)
AS
BEGIN
DECLARE #SQL NVARCHAR(MAX)
SET #SQL = '
CREATE TABLE ' + #tableName + ' (
id INT NOT NULL
)'
--PRINT #SQL
EXEC sys.sp_executesql #SQL
END
GO
EXEC dbo.tableCreation #tableName = 'Employee'

SQL, Assign Select Column to Variable

I am using SQL Server 2012, I am going to Create Store Procedure which copies a column from a table in a variable, Could any one please tell me what is Wrong with this code?
alter Procedure Id_Fetch
#Col varchar(50)=null,
#Table VARCHAR(50)=Null,
#OrdrBy Varchar(40)=null
as
Begin
declare #TempCol nvarchar (100)
Exec(' SELECT '+#TempCol+' = '+#Col+' from ' + #Table +' order by '+#OrdrBy )
its showing error "Incorrect Syntax near '='
A little modification ...... Use TOP 1 in your select as if more than one value is returned by your select it will throw an error.
Use SYSNAME datatype for your Column names and table names.
Use QUOTENAME() function around your object name parameters, which puts square brackets [] around the passed parameter value and forces it to be treated as an object name (Protection against Sql Injection attack).
Use sp_executesql instead of EXEC and concatenating parameter values into string and executing again protects you against Sql Injection attack.
ALTER PROCEDURE Id_Fetch
#Col SYSNAME,
#Table SYSNAME,
#OrdrBy SYSNAME,
#Col_Value NVARCHAR(100) OUTPUT
AS
BEGIN
SET NOCOUNT ON;
DECLARE #Sql NVARCHAR(MAX);
SET #Sql = N' SELECT TOP 1 #Col_Value = ' + QUOTENAME(#Col)
+ N' FROM ' + QUOTENAME(#Table)
+ N' ORDER BY ' + QUOTENAME(#OrdrBy)
EXECUTE sp_executesql #Sql
,N'#Col_Value NVARCHAR(100) OUTPUT'
,#Col_Value OUTPUT
END

Resources