Я не верю, что оцененный оператор доступен, что означает, что ваш пример запроса 'Select @FooBar' никогда не сохраняется нигде, как 'Select 364556243'
Даже в трассировке профилировщика вы увидите, что оператор попадет в кеш как '(@Foobar int) select @ foobar'
Это имеет смысл, поскольку большое преимущество использования sp_executesql заключается в том, что он может кэшировать оператор в надежной форме без оцениваемых переменных, в противном случае, если он заменит переменные и выполнит этот оператор, мы просто увидим, как план выполнения будет раздуваться.
обновлено: Вот шаг в правильном направлении :
Все это можно было бы очистить и обернуть в красивую функцию с входными данными (@Statement, @ParamDef, @ParamVal) и возвращать «подготовленный» оператор. Я оставлю это как упражнение для вас, но, пожалуйста, отправляйте сообщения, когда вы улучшите его!
Здесь используется функция разделения ссылка
set nocount on;
declare @Statement varchar(100), -- the raw sql statement
@ParamDef varchar(100), -- the raw param definition
@ParamVal xml -- the ParamName -to- ParamValue mapping as xml
-- the internal params:
declare @YakId int,
@Date datetime
select @YakId = 99,
@Date = getdate();
select @Statement = 'Select * from dbo.Yak where YakId = @YakId and CreatedOn > @Date;',
@ParamDef = '@YakId int, @Date datetime';
-- you need to construct this xml manually... maybe use a table var to clean this up
set @ParamVal = ( select *
from ( select '@YakId', cast(@YakId as varchar(max)) union all
select '@Date', cast(@Date as varchar(max))
) d (Name, Val)
for xml path('Parameter'), root('root')
)
-- do the work
declare @pStage table (pName varchar(100), pType varchar(25), pVal varchar(100));
;with
c_p (p)
as ( select replace(ltrim(rtrim(s)), ' ', '.')
from dbo.Split(',', @ParamDef)d
),
c_s (pName, pType)
as ( select parsename(p, 2), parsename(p, 1)
from c_p
),
c_v (pName, pVal)
as ( select p.n.value('Name[1]', 'varchar(100)'),
p.n.value('Val[1]', 'varchar(100)')
from @ParamVal.nodes('root/Parameter')p(n)
)
insert into @pStage
select s.pName, s.pType, case when s.pType = 'datetime' then quotename(v.pVal, '''') else v.pVal end -- expand this case to deal with other types
from c_s s
join c_v v on
s.pName = v.pName
-- replace pName with pValue in statement
select @Statement = replace(@Statement, pName, isnull(pVal, 'null'))
from @pStage
where charindex(pName, @Statement) > 0;
print @Statement;