I've found an interesting difference in behavior between executing a dynamic SQL string and using sp_executesql. I've illustrated the difference in code below, using the example for sp_executesql from BOL. I need to execute a query with a filter like, "WHERE Id IN (1,2)". Executing a fully concatenated string runs fine, but there's no query plan reuse. Using sp_executesql in order to leverage query plan reuse results in this error:
Server: Msg 245, Level 16, State 1, Line 1
Syntax error converting the varchar value '32,35' to a column of data type tinyint.
Any ideas?
DECLARE @IntVariable INT
DECLARE @SQLString NVARCHAR(500)
DECLARE @ParmDefinition NVARCHAR(500)
/* Build the SQL string once.*/
SET @SQLString =
N'SELECT * FROM pubs.dbo.employee WHERE job_lvl = @level'
SET @ParmDefinition = N'@level tinyint'
/* Execute the string with the first parameter value. */
SET @IntVariable = 35
EXECUTE sp_executesql @SQLString, @ParmDefinition,
@level = @IntVariable
/* Execute the same string with the second parameter value. */
SET @IntVariable = 32
EXECUTE sp_executesql @SQLString, @ParmDefinition,
@level = @IntVariable
-- Level IDs to include
DECLARE @vcVariable VARCHAR(100)
SET @vcVariable = '32,35'
-- Succeeds
SET @SQLString =
N'SELECT * FROM pubs.dbo.employee WHERE job_lvl IN (' + @vcVariable + ')'
EXECUTE(@SQLString)
-- Fails
SET @SQLString =
N'SELECT * FROM pubs.dbo.employee WHERE job_lvl IN (@level)'
SET @ParmDefinition = N'@level varchar(100)'
/* Execute the string with the first parameter value. */
EXECUTE sp_executesql @SQLString, @ParmDefinition,
@level = @vcVariable
Server: Msg 245, Level 16, State 1, Line 1
Syntax error converting the varchar value '32,35' to a column of data type tinyint.
Any ideas?
DECLARE @IntVariable INT
DECLARE @SQLString NVARCHAR(500)
DECLARE @ParmDefinition NVARCHAR(500)
/* Build the SQL string once.*/
SET @SQLString =
N'SELECT * FROM pubs.dbo.employee WHERE job_lvl = @level'
SET @ParmDefinition = N'@level tinyint'
/* Execute the string with the first parameter value. */
SET @IntVariable = 35
EXECUTE sp_executesql @SQLString, @ParmDefinition,
@level = @IntVariable
/* Execute the same string with the second parameter value. */
SET @IntVariable = 32
EXECUTE sp_executesql @SQLString, @ParmDefinition,
@level = @IntVariable
-- Level IDs to include
DECLARE @vcVariable VARCHAR(100)
SET @vcVariable = '32,35'
-- Succeeds
SET @SQLString =
N'SELECT * FROM pubs.dbo.employee WHERE job_lvl IN (' + @vcVariable + ')'
EXECUTE(@SQLString)
-- Fails
SET @SQLString =
N'SELECT * FROM pubs.dbo.employee WHERE job_lvl IN (@level)'
SET @ParmDefinition = N'@level varchar(100)'
/* Execute the string with the first parameter value. */
EXECUTE sp_executesql @SQLString, @ParmDefinition,
@level = @vcVariable