Use numeric inside SQL statement in procedure - sql-server

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.

Related

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

Using dynamic WHERE clause with sp_executesql

I can not get dynamic where clause working. The query I use:
IF NOT EXISTS ( SELECT *
FROM sys.tables
WHERE name = 'a' )
BEGIN
CREATE TABLE a ( a INT );
END;
DECLARE #whereClause NVARCHAR(MAX) = ' 1=1 ';
DECLARE #sql NVARCHAR(MAX) = 'SELECT * FROM a WHERE #whereClause';
EXEC sp_executesql #sql, N'#whereClause NVARCHAR(MAX)', #whereClause;
DROP TABLE a;
Then additional question would be: is there any possibility to debug query that is executed with sl_executesql?
As as been stated you can't use the parameters on sp_executesql to replace statement objects, only parameter variables.
If you need to build the WHERE clause dynamically, I find it easier to use REPLACE for the Object components of the statement.
DECLARE #whereClause NVARCHAR(MAX) = ' 1=#whereVariable ';
DECLARE #whereVariable INT = 1;
DECLARE #sql NVARCHAR(MAX) = 'SELECT * FROM a WHERE #whereClause';
SELECT #sql = REPLACE(#sql, '#whereClause', #whereClause)
EXEC sp_executesql #sql
,'#whereVariable INT'
,#whereVariable = #whereVariable;
This means that the statement can be built without interlived + and variables. It then means that the input and output parameters are used as normal.

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().

Dynamic Column Name in SQL in Update statement

DECLARE #sql NVARCHAR(max)
DECLARE #ParmDefinition NVARCHAR(500)
SET #sql = 'UPDATE [Table1] SET [Table1].[#columnName] = TEST';
SET #ParmDefinition = N'#columnName NVARCHAR(50)';
EXEC sp_executesql #sql, #ParmDefinition, #columnName = N'MyColumn';
When I run the above query, I get Invalid column name '#columnName'.. Clearly, the column name is not being replaced when the query is run.
In reality, my #sql variable is much larger and I have many columns I wish to update, thus I would like to avoid doing SET SQL = for all enumerations of the column name.
I'd like to declare the sql string once, and invoke the query with different values. e.g.:
EXEC sp_executesql #sql, #ParmDefinition, #columnName = N'MyColumn';
EXEC sp_executesql #sql, #ParmDefinition, #columnName = N'AnotherColumn';
EXEC sp_executesql #sql, #ParmDefinition, #columnName = N'YetAnotherColumn';
-- And so on
Is something like this possible?
Yes, you have to concatenate the variable outside the string. In other words:
SET #sql = 'UPDATE [Table1] SET [Table1].[' + #columnName + '] = t1.Value ' +
EDIT: Another solution we have used is to replace tokens in the base sql to construct a new sql variable for execution.
DECLARE #sql nvarchar(max) = 'SELECT #ColumnName FROM #TableName';
DECLARE #sql2 nvarchar(max) = REPLACE(REPLACE(#sql,'#ColumnName',#ColumnNameVariable),'#TableName',#TableNameVariable)
EXEC (#sql2)
...Some code that changes the values of #ColumnNameVariable and #TableNameVariable...
DECLARE #sql2 nvarchar(max) = REPLACE(REPLACE(#sql,'#ColumnName',#ColumnNameVariable),'#TableName',#TableNameVariable)
EXEC (#sql2)
And you'll notice that the Declaration and Exec of SQL2 are exactly the same lines in both cases. This lends itself to use in a LOOP if that is applicable. (Except that you wouldn't DECLARE #Sql2 in the loop...just populate/re-populate it).
First of all, kudos for trying to parameterize your dsql using sp_executesql. The problem is, you can only parameterize something you could put into a variable in the first place such as in a search predicate or select list.
However it's still possible; just concatenate the column name with your DSQL string, wrapping it with the quotename function
set #sql = 'update table1 set table1.' + quotename(#ColumnName) + ' = ...

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