我讀過在存儲過程中使用動態SQL可能會損害存儲過程的性能。我想這個理論是,存儲過程不會存儲通過EXEC或sp_executesql執行的SQL的執行計劃。動態SQL和存儲過程優化
我想知道,如果這是真的。如果這是真的,我是否有與多個嵌套的IF塊相同的問題,每個塊都有我的SQL語句的不同「版本」?
我讀過在存儲過程中使用動態SQL可能會損害存儲過程的性能。我想這個理論是,存儲過程不會存儲通過EXEC或sp_executesql執行的SQL的執行計劃。動態SQL和存儲過程優化
我想知道,如果這是真的。如果這是真的,我是否有與多個嵌套的IF塊相同的問題,每個塊都有我的SQL語句的不同「版本」?
如果您有多個嵌套的IF塊則SQL Server將能夠存儲的執行計劃。 我假設IF是直接的,例如。 @如果參數1 IS NOT NULL
SchmitzIT的答案是正確的SQL Server還可以存儲用於動態SQL的執行路徑。然而,只有sql被正確構建和執行,這纔是真實的。
通過適當建,我的意思是顯式聲明的參數和傳遞他們對sp_executesql。例如
declare @Param1 nvarchar(255) = 'foo'
,@Param2 nvarchar(255) = 'bar'
,@sqlcommand nvarchar(max)
,@paramList nvarchar(max)
set @paramList = '@Param1 nvarchar(255), @Param2 nvarchar(255)'
set @sqlcommand = N'Select Something from Table where Field1 = @Param1 AND Field2 = @Param2'
exec sp_executesql @statement = @sqlcommand
,@params = @paramList
,@Param1 = @Param1
,@Param2 = @Param2
正如您所看到的,sqlcommand文本不會硬編碼要使用的參數值。它們在EXEC sp_executesql的
分別通過如果你寫壞舊的動態SQL
set @sqlcommand = N'Select Something from Table where Field1 = ' + @Param1 + ' AND Field2 = ' + @Param2
exec sp_executesql @sqlcommand
那麼SQL Server將無法存儲執行計劃
這是MSDN不得不說些什麼。我強調了相關位對您的問題
sp_executesql的具有如針對批次, 名稱的範圍,數據庫上下文中執行相同的行爲。 直到 的執行sp_executesql語句的Transact-SQL語句 或批處理的sp_executesql的@stmt參數未編譯。 @stmt的內容是 ,然後編譯並執行一個執行計劃,該執行計劃與調用sp_executesql的批處理的 執行計劃分開。 sp_executesql批處理無法引用調用sp_executesql的批處理 中聲明的變量。調用 sp_executesql的批處理對 sp_executesql批處理中的本地遊標或變量不可見。數據庫上下文中的更改僅持續到 sp_executesql語句的末尾。
sp_executesql的可以用來代替的存儲過程時,在參數的變化值 的說法是唯一的變化來執行 的Transact-SQL語句多次。由於的Transact-SQL語句 本身保持不變,僅參數值 變化,SQL Server查詢優化器可能會重用它產生了第一次執行的 執行計劃。
我在考慮是用動態的情況下, SQL來確定在SELECT中使用哪種where子句。 AFAIK,我不能參數化我的查詢,因爲我沒有使用參數作爲字段值。 或者有沒有辦法參數化where子句? – Finster
不,我不認爲where子句可以被參數化,因爲where子句是SQL命令的一部分。這聽起來像你的動態SQL本質上是靜態的,但它有不同的風格。我想你只是想減少代碼重複。我想唯一可以肯定的就是加速測試這兩種風格,但在你的情況下,我希望可以忽略不計的差異。 – DeanOC
@DeanOC你爲什麼在執行級別使用Name = Value方法(例如statement = sqlcommand等)?這不會是相同的exec sp_executesql sqlcommand,paramList,Param1,Param2你指的是正確地構建動態SQL,其中params不是硬編碼,這是這裏的情況。只是好奇! – SQLnbe