Dynamic SQL gives "Incorrect Syntax Near '+'" - sql

I am probably being extremely dumb here but why does this simple dynamic query:
EXEC sp_executesql N'SELECT Id FROM dbo.Widgets WHERE Id = ' + 1;
Give "Incorrect syntax near '+'"
?

You can't formulate the expression as part of the argument. And you shouldn't be concatenating that way anyway (think SQL injection) - you're using sp_executesql already, why not use a proper parameter?
DECLARE #Id INT, #sql NVARCHAR(MAX);
SET #Id = 1; -- presumably this will come from elsewhere
SET #sql = N'SELECT Id FROM dbo.Widgets WHERE Id = #Id;';
EXEC sp_executesql #sql, N'#Id INT', #Id;

Related

Setting SQL Variable via Dynamic SQL

I know I am overthinking this, but I've been banging against this for too long so I'm reaching out for help.
This is the statement I'm trying to run: SELECT #cntMax = MAX(id) FROM [Raw_Item-FieldReport]
BUT, the table name is a variable #reportTable
This doesn't work:
SET #sql = 'SELECT #cntMax = MAX(id) FROM #reportTable'
EXEC sp_executesql #sql
I even tried having the actual table name in the SET #sql and that doesn't work either.
I didn't think it would be this difficult, please tell me I'm missing something easy/obvious.
Here's the full bit of code for those who want it:
DECLARE
#inTable nvarchar(255) = 'Raw_Item',
#reportTable nvarchar(255),
#fieldName nvarchar(255),
#cnt int,
#cntMax int,
#sql nvarchar(max)
SET #reportTable = #inTable + '-FieldReport'
SET #cnt = 1
SELECT #cntMax = MAX(id) FROM [Raw_Item-FieldReport]
PRINT #cntMax
SET #cntMax = 0
SET #sql = 'SELECT #cntMax = MAX(id) FROM [Raw_Item-FieldReport]'
EXEC sp_executesql #sql
PRINT #cntMax
SQL Server 12.0.2008.8 (on Azure)
You need to use an output parameter, otherwise SQL Server has no idea how to connect #cntMax in the dynamic SQL to #cntMax not in the dynamic SQL, since they are different scopes. And to protect yourself from SQL injection (some tips here and here), always check that your object exists, and use QUOTENAME() as opposed to manually adding square brackets (and you should always use QUOTENAME() when building object names from user input or variables, even when they don't have bad characters like dashes):
DECLARE #sql nvarchar(max),
#inTable nvarchar(255) = N'Raw_Item',
#reportTable nvarchar(255);
SET #reportTable = N'dbo.' + QUOTENAME(#inTable + '-FieldReport');
IF OBJECT_ID(#reportTable) IS NOT NULL
BEGIN
SET #sql = N'SELECT #cntMax = MAX(id) FROM ' + #reportTable + N';';
EXEC sys.sp_executesql #sql,
N'#cntMax int output',
#cntMax = #cntMax OUTPUT;
PRINT #cntMax;
END
ELSE
BEGIN
PRINT 'Nice try, h#xx0rs!';
END
Always use schema reference (dbo), always use statement terminators, and please try to avoid naming things with invalid identifier characters like dash (-). And one additional tip: always use N prefix on N'nvarchar string literals'.

Removing NULL with COALESCE in Dynamic SQL

I have some dynamic SQL as part of a stored procedure I want to execute:
SET #SQL_TXT = 'INSERT INTO ' +#ENTY_TABLE_NAME+
'([ITEM_NAME]
,[ADD_DTT]
,[ADD_USR]
,[UPD_DTT]
,[UPD_USR]
,[ACTIVE_IND]
,[ITEM_PK])
VALUES
('''+#UPD_VALUE+'''
, CURRENT_TIMESTAMP
, '''+#UPD_USR_DOM_NAME+''', CURRENT_TIMESTAMP,'''+#UPD_USR_DOM_NAME+''',''Y'','''+#ITEM_PK+''');
SET #Id = SCOPE_IDENTITY();
RETURN;'
This runs fine, but ITEM_NAME can't be NULL so I want to ad a COALESE():
SET #SQL_TXT = 'INSERT INTO ' +#ENTY_TABLE_NAME+
'(COALESCE([ITEM_NAME], '')
,[ADD_DTT]
,[ADD_USR]
,[UPD_DTT]
,[UPD_USR]
,[ACTIVE_IND]
,[ITEM_PK])
VALUES
('''+#UPD_VALUE+'''
, CURRENT_TIMESTAMP
, '''+#UPD_USR_DOM_NAME+''', CURRENT_TIMESTAMP,'''+#UPD_USR_DOM_NAME+''',''Y'','''+#ITEM_PK+''');
SET #Id = SCOPE_IDENTITY();
RETURN;'
But I am getting this error:
Incorrect syntax near the keyword 'COALESCE'.
Unclosed quotation mark after the character string ');
SET #Id = SCOPE_IDENTITY();
RETURN;'.
Incorrect syntax near '='.
For the life of me I don't see where this ')' is. What am I doing wrong?
Edit: here is the exec
EXECUTE SP_executesql #SQL_TXT, N'#Id INTEGER OUTPUT', #Id OUTPUT
You can not put coalesce() around the column name destination of your insert, you use it around the value being inserted.
SET #SQL_TXT = 'INSERT INTO ' +#ENTY_TABLE_NAME+
'([ITEM_NAME]
,[ADD_DTT]
,[ADD_USR]
,[UPD_DTT]
,[UPD_USR]
,[ACTIVE_IND]
,[ITEM_PK])
VALUES
('''+coalesce(#UPD_VALUE,'')+'''
, CURRENT_TIMESTAMP
, '''+#UPD_USR_DOM_NAME+''', CURRENT_TIMESTAMP,'''+#UPD_USR_DOM_NAME+''',''Y'','''+#ITEM_PK+''');
SET #Id = SCOPE_IDENTITY();
RETURN;'
Note: #UPD_USR_DOM_NAME is inserted into two different columns. Not sure if that is intentional, just thought I would point it out.
You can also fully parameterize the rest of your values for use with sp_executesql instead of concatenating them like that. (Guessing at the data types of your parameters in this example)
declare #sql nvarchar(max);
declare #params nvarchar(max);
declare #id int;
set #sql = N'INSERT INTO ' +#ENTY_TABLE_NAME+'([ITEM_NAME] ,[ADD_DTT] ,[ADD_USR] ,[UPD_DTT] ,[UPD_USR] ,[ACTIVE_IND] ,[ITEM_PK])
VALUES (coalesce(#UPD_VALUE,''), CURRENT_TIMESTAMP, #UPD_USR_DOM_NAME, CURRENT_TIMESTAMP,#UPD_USR_DOM_NAME,''Y'',#ITEM_PK);
SET #Id = SCOPE_IDENTITY();
RETURN;'
set #params = N'#UPD_VALUE varchar(32),#UPD_USR_DOM_NAME varchar(32), #ITEM_PK varchar(32), #Id INTEGER OUTPUT';
EXECUTE SP_executesql #sql, #params, #UPD_Value, #UPD_USER_DOM_NAME, #ITEM_PK, #Id = #Id OUTPUT;
dynamic sql reference:
The curse and blessings of dynamic SQL - Erland Sommarskog
sp_executesql

Get error in string query

I'm a beginner to SQL Server
I wrote this query:
DECLARE #sql nvarchar(1000) = 'UPDATE Work
SET [Name] = Programmer, [ImageAddress] = pic.jpg
WHERE Id = 2'
SELECT #sql
EXEC Sp_executesql #sql
but I get this error
Invalid column name 'Programmer'.
Why do I get this error?
Thank you for your help
You are dealing with SQL in strings. Quoting the strings becomes a challenge. You need for Programmer to be in single quotes when the query is executed. To get this, you need double single quotes in the string:
DECLARE #sql nvarchar(1000)='
UPDATE Work
SET [Name] = ''Programmer'', [ImageAddress] = ''pic.jpg'' WHERE Id=2'
select #sql
EXEC Sp_executesql #sql;
Because you are wise enough to use sp_executesql, you should learn about parameters. You can write the query as:
DECLARE #sql nvarchar(1000)='
UPDATE Work
SET [Name] = #Programmer, [ImageAddress] = #imageaddress WHERE Id=2'
select #sql
EXEC Sp_executesql #sql, N'#programmer nvarchar(255), #imageaddress nvarchar(255)',
#programmer = N'Programmer', #imageaddress = N'pic.jpg';
This has several advantages besides the quoting. It is safer in terms of SQL injection and it allows SQL Server to cache the execution plans if the query is called more than once.
try this:
You need to use '' (Double Quotes for string) Inside Dynamic SQL
DECLARE #sql nvarchar(1000)='
UPDATE Work
SET [Name] = ''Programmer'',[ImageAddress] =''pic.jpg'' WHERE Id=2'
select #sql
EXEC Sp_executesql #sql

Declare variable and use in query

Please consider the following
declare #MyField varchar(255);
set #MyField = 'MyDatabaseField';
select distinct Table.#MyField
from Table
This results in the error Incorrect syntax near #MyField. Then I tried:
select distinct Table.['+#MyField+']
from Table
However, this results in an Incorrect column name error.
How do I correctly use the #MyField in this query? I'm on SQL Server 2008.
Please try executing by building a string.
declare #MyField varchar(255);
set #MyField = 'MyDatabaseField';
exec ('select distinct Table.'+#MyField+' from Table')
Refer sp_executesql (Transact-SQL), Using sp_executesql
You should use dynamic SQL to achieve that. You can use sp_executesql stored proc to do that. Please not that I changed your variable declaration to **N**VARCHAR.
declare #MyField nvarchar(255)
set #MyField = N'MyDatabaseField'
declare #sql nvarchar(max) = N'select distinct ' + #MyField + N' from TableName'
exec sp_executesql #sql

How to pass a table variable using sp_executesql

I'm trying to create a table using sp_executesql but I keep getting an error that says "Incorrect syntax near '#_TableName'. Any idea what I'm doing wrong here?
Here's the code that I'm using:
DECLARE #SQLString NVARCHAR(MAX),
#ParamDefinition NVARCHAR(MAX),
#TableName NVARCHAR(MAX);
SET #TableName = N'[dbo].[MyTable]';
SET #SQLString = N'SELECT * FROM #_TableName;';
SET #ParamDefinition = N'#_TableName NVARCHAR(max)';
EXEC sp_executesql #SQLString, #ParamDefinition,
#_TableName = #TableName;
That yields the error:
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near '#_TableName'.
If I hard code the table name and the column type (I have to do both) then the query works, otherwise I get the incorrect syntax message for both those variables.
In case you're wondering, I want to put this code inside a stored procedure, so that if anyone wants to create or modify a table then they call this stored procedure which can run additional validations.
Figured out the problem.
Apparently sp_executesql expects the parameter definition for a table to be of a table type (see this answer for an example: https://stackoverflow.com/a/4264553/21539).
An easier way to solve this problem was to insert the variables names directly into the SQLStatement string as follows:
DECLARE #SQLString NVARCHAR(MAX),
#TableName NVARCHAR(MAX);
SET #TableName = N'[dbo].[MyTable]';
SET #SQLString = N'SELECT * FROM ' + #TableName + ';';
SET #ParamDefinition = N'#_TableName NVARCHAR(max);
EXEC sp_executesql #SQLString;