2017-02-10 74 views
2

我有一些使用動態SQL的存儲過程。 我真的想改變它們,使它們不是動態的,純粹是因爲它們可能非常煩人,因爲錯誤處理(單擊錯誤消息不會導致錯誤)而進行故障排除和更改。我知道我可以選擇文本並將其作爲常規SQL來粘貼,以幫助解決這個問題,但這非常令人沮喪。替代動態SQL

我遇到的問題是,查詢在非動態時運行速度慢得多。具體來說,動態查詢中的where子句由於其靈活性增加而快得多。例如,靜態where子句會是這樣的:

where 
    SomeColumn = case when @variable1 = 0 then SomeColumn else @variable1 end 
and(
    (@variable2 = -2 and SomeColumn2 = 1) 
    or (@variable2 = -1) 
    or (@variable2 = 0 and SomeColumn2 = 0 and SomeColumn3 = 0) 
    or (@variable2 = 1 and SomeColumn2 = 0 and SomeColumn3 > 0) 
    ) 

但動態where子句是:

where ' + @SomeCondition + @SomeCondition2 + ' 

使用CASE語句,像這樣:

declare @SomeCondition nvarchar(max) = case 
    when @variable3 = -2 then N'Condition 1' 
    when @variable3 = 0 then N'Condition 2' 
    when @variable3 = 1 then N'Condition 3' 
    else N'' 
    end 

唯一我能想到的解決方案是使用多個if語句,並且只更改每個語句中的where子句,但這看起來非常浪費且耗時。

是否有其他動態SQL的替代方案? 如果失敗了,有什麼我可以做的,讓sql服務器指示我正確的錯誤?

+0

您是否使用'try' /'catch'來獲取由動態SQL引起的錯誤?也許修復錯誤處理會做你需要的。除非使用'recompile'選項,否則即使是多個if也可能有問題。 –

+0

這將是非常有益的,令人沮喪的錯誤處理幾乎是我想更改動態查詢的唯一原因。我會在包含SQL的變量中使用try/catch嗎?還是需要將它寫在外部?我不完全確定如何通過動態SQL來解決這個問題。 –

+1

您可以制定專門的,優化的程序,然後根據您的參數調用適當的程序,這樣可以避免OR條件。但是,你會有更多的程序來維護。根據我的經驗,你永遠不會得到一個「一刀切」的查詢(在哪裏)或者動態查詢或專用查詢。 –

回答

3

OPTION (RECOMPILE)添加到查詢中。這將導致它在每次執行時都被重新編譯,而且優化器足夠聰明,可以簡化並消除謂詞,就像現在使用動態SQL一樣。

+0

這使得我的查詢速度更快(謝謝!),但點擊錯誤消息後,它仍然會將我帶到查詢中的隨機位置。我在執行的SQL變量內的查詢末尾添加了「選項(重新編譯)」。 –

+0

對於複雜的查詢,發生錯誤的行號可能是騙人的。另外,您可能會碰到這個已知問題:https://connect.microsoft.com/SQLServer/feedback/details/857794/。無論如何,很高興這至少有助於表現。 – dean

+0

我的查詢結構是這樣的:'declare @SQLText nvarchar(max)= N'BigQueryGoesHere選項(重新編譯)'exec sys.sp_executesql @ SQLText' 這應該返回錯誤嗎?當我選擇查詢文本並將其作爲標準SQL粘貼時,我指向了正確的位置。 –

1

或者,您可以使用如下的ISNULL(NULLIF語法。但請謹慎使用,否則可能會對性能造成負面影響。

where 
    SomeColumn = ISNULL(NULLIF(@variable1,''),SomeColumn) and 
    SomeColumn2 = ISNULL(NULLIF(@variable2,''),SomeColumn2) and 
    and so on.. 
+0

我試過這個,但不幸的是,它的確顯着減慢了查詢速度。 –