I tried the following:
declare @var2 nvarchar(30)
declare @qsql nvarchar(100)
set @var2 = N'iddelegat'
exec ('select max('+ @var2 + ') as IDexec from delegat');
set @qsql = 'select max(@varsp) as IDspexec from delegat';
exec sp_executesql @qsql, N'@varsp nvarchar(30)', @var2;
And the result:
IDexec IDspexec
-----------------------
500038 iddelegat
I could not understand why sp_executesql
does not return the same result as EXECUTE
. The right returned values are only in EXECUTE
statement. It seems that sp_executesql
does not evaluate the string 'iddelegat' to return the column.
You cannot parameterize column names or table names when using
sp_executesql
. So, when you plug in the valueiddelegat
in theexec()
, you are getting the column. When you have it as a parameter tosp_executesql
, you are getting'iddelegat'
-- a string with the name of the column.The issue of what you can parameterize is not well explained in the SQL documentation. If you dig far enough, you will get this:
This is in an obscure part of the documentation, but it has the correct general idea.
To help further understand this, the SQL engine can compile queries with parameters to get the execution plan. To do this, it needs to know the actual columns and tables in the query. Extra values -- parameters -- can be plugged in after the compilation step.
You can't parameterise column names.
Your attempt is basically the same as doing
MAX(N'iddelegat')
notMAX(iddelegat)
The only way of using these in dynamic SQL is to concatenate them into the string directly.
You should use the
quotename
function if doing so to mitigate against SQL injection possibilities.See The curses and blessings of dynamic SQL