我不相信評估的說法是可用的,這意味着你的例子查詢「選擇@FooBar」是永遠不會在任何地方持續爲即使在事件探查器跟蹤「選擇364556243」
,你會看到聲明命中緩存爲「 (@Foobar int)select @foobar'
這很有意義,因爲使用sp_executesql的一大好處是它能夠以可靠的形式緩存語句而不用評估變量,否則如果它替換變量並執行聲明我們只會看到執行計劃膨脹。
更新:這裏有一個一步在正確的方向:
所有這一切都可以被清理,幷包裹在一個不錯的功能,具有輸入(@Statement,@ParamDef,@ParamVal)和將返回「準備好的」聲明。我會將其中的一部分作爲練習留給你,但是當你改進時請回復!
從這裏link
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;
使用分割功能只是爲了讓您的使用場景中更好的畫面,這是你的東西進行性能優化,故障排除問題,審計,其他一些目的做更多的時候? – 2011-05-06 21:04:53
@Phil Helmer,通常用於問題故障排除,但偶爾會在執行一些更令人困惑的動態查詢時進行性能調整。 – 2011-05-09 19:50:12