2013-02-07 58 views
1

請考慮採用某些參數的以下示例過程。存儲過程中可選參數的最佳解決方案

Create Procedure CustomerSearch(
@Name  nVarChar(100) = Null, 
@Phone  nVarChar(100) = Null, 
@Address nVarChar(100) = Null, 
) 
As 

Select * 
     From dbo.CustomerView 
     Where (@Name  is Null or Name  = @Name) And 
       (@Phone  is Null or Phone = @Phone) And 
       (@Address is Null or Address = @Address) 

因爲參數的值可能爲空,所以我找到兩個解決方案來處理它。

  1. 使用或contition這樣的: (@Name爲空或名稱= @Name)
  2. 使用動態SQL,並添加條件進行查詢,如果參數值不爲空。

在CustomerView視圖中存在多個表連接,並且此表具有大量數據並且性能非常重要。解決方案1有開銷(執行計劃)。由於某些原因,我無法使用動態sql。有更好的方法來建立這個查詢?

當我使用條件@Name是Null或Name = @Name)而不是Name = @Name並查看執行計劃時,索引查找成本增加。

+3

您可能會發現此資源有用:[T-SQL中的動態搜索條件](http://www.sommarskog.se/dyn-search.html)。 –

回答

2

你的代碼工作正常,爲了你的情況,我會將參數包裝在NULLIF(@Parameter,'')中以防止空白被比較。

下面是編寫查詢的另一種方法。如果該參數爲空或爲空,則會將列與自身進行比較,總是爲真。

Name = COALESCE(NULLIF(@Name,''),Name) 

http://sqlfiddle.com/#!3/4ff42/1

2

您上面張貼的代碼完全可以接受。如果性能出現問題,請確保名稱,電話和地址列上有索引。

+0

我在這個列上創建了索引,它不是我的問題。當我運行查詢時需要太多的時間,並且當我查看執行計劃時(檢查空參數)採用進程與使用name = @name條件。 –

+0

您能否提供創建的索引? – UnhandledExcepSean

+0

我創建了所有列的單一索引,名稱索引,手機索引和... –

1

你可能也想看看添加OPTION (RECOMPILE)到您的存儲過程的結束。

無論何時存儲過程第一次在SQL Server中運行,它都經過優化,查詢計劃被編譯並緩存在SQL Server的內存中。

MSDN article

RECOMPILE
指示SQL Server數據庫引擎來丟棄它執行後查詢生成的計劃,迫使查詢優化器下一次重新編譯查詢計劃相同的查詢被執行。沒有指定RECOMPILE,數據庫引擎會緩存查詢計劃並重新使用它們。編譯查詢計劃時,查詢提示使用查詢中任何局部變量的當前值,並且如果查詢位於存儲過程中,則將當前值傳遞給任何參數。
RECOMPILE是創建使用WITH RECOMPILE子句的存儲過程時的有用替代方法,因爲只有存儲過程中的一部分查詢而不是整個存儲過程必須重新編譯時。有關更多信息,請參閱重新編譯存儲過程。 當您創建計劃指南時,RECOMPILE也很有用。

+0

好的。請注意,我的問題是條件(@Name爲Null或Name = @Name)而不是Name = @Name索引查找成本增加。 –