2012-02-21 34 views
2

我有一種情況,我調用存儲過程並傳入一些變量。在某些情況下,我將傳入null,並且我希望它返回所有內容。採取以下(年齡是整數列):T-SQL其中int = @ var/@ var = null?

[Table] 
[Name] | [Age] 
Mike | 22 
Fred | 18 
Bob | 22 



SELECT * FROM [table] WHERE [Age][email protected] 

現在,如果我通過22我會得到邁克和鮑勃。同樣在18歲時傳球會讓我得到弗雷德。但是,如果我想要全部3行,當我傳入null /不設置@AgeVar?這是一個非常簡單的問題。

編輯:雜誌是非常複雜的,我真的不想要所有的部分,因爲不得不在兩倍於下面的答案之一。還有其他方法嗎?

+5

閱讀[Catch-all queries](http://sqlinthewild.co.za/index.php/2009/03/19/catch-all-queries/) – 2012-02-21 17:26:02

+2

如果您沒有時間點擊Joe的鏈接到他非常優秀的文章,他表明使用動態SQL可能會超越這種方法。 – DOK 2012-02-21 17:45:06

+1

@DOK:要說清楚,我不是該文章的作者。那篇文章是由Gail Shaw撰寫的,他比我在SQL Server上聰明得多。 – 2012-02-21 17:46:58

回答

9
SELECT * FROM [table] WHERE [Age][email protected] OR @AgeVar IS NULL 

正如上面和下面提到的無數次,這種技術將會導致大型表的查詢性能下降。用戶要小心。

+0

這是一個很好的答案。從來沒有想過這樣做。輝煌。我會在一段時間內將它標記爲答案,因爲它說我已經知道了什麼。但是,謝謝! – Piercy 2012-02-21 17:32:33

+8

JUST FYI ...這對SqlServer中的查詢執行計劃造成嚴重破壞......我們最近不得不重構一堆SPROC,因爲像上面這樣的查詢。 – 2012-02-21 17:34:35

+1

@EoinCampbell:這是我在我對這個問題的評論中引用的博文的要點。 – 2012-02-21 17:41:25

3
IF @AgeVar IS NULL 
    BEGIN 
     SELECT * 
     FROM @Table 
    END 
ELSE 
    BEGIN 
     SELECT * 
     FROM @Table 
     WHERE Age = @AgeVar 
    END 
+0

是的,我正在考慮像這樣的東西,但存儲程序我這樣做是非常巨大的,並不真的想要將每個部分分爲兩部分只是爲了這個。是否有任何其他方式? – Piercy 2012-02-21 17:27:28

+0

已發佈'OR'選項將工作,就像'WHERE \t ISNULL(@ AgeVar,[Age])= [Age]'但是上面提到的選項可以被優化器處理得更好,你可以考慮創建一個臨時表,用'IF ...'填充它ELSE'然後在程序後面提到,但是這可能會變得更糟,這取決於程序的其餘部分和指示等。 – GarethD 2012-02-21 17:39:47

+0

我會關心用這個查詢計劃緩存。 – 2012-02-21 17:42:17

1

我發現如果您有一個常見的情況,那麼請使用CASE語句。這將使性能僅在極少數情況下拖動。所以,如果你更經常地傳入null作爲參數,那麼這將會更有效率。

SELECT * 
FROM [table] 
WHERE 
    0 = 
     CASE 
      WHEN @AgeVar IS NULL THEN 0 
      WHEN [Age][email protected] THEN 0 
     END 
+0

我還沒有真正測試過這個,但在我看來,這將無法正常工作:如果[Age] = @AgeVar,那麼最終查詢將最終看起來像 select * from [table] where 0 = 0 ...你最終會得到所有的記錄! – 2012-03-06 23:20:31

+0

我在很多情況下都使用這種方法取得巨大成功。想想SQL如何工作,這應該是有道理的。它類似於存在。 select * from [table] where 0 = 0僅在當前被評估的行的[Age]列等於@AgeVar的情況下發生。通過你的邏輯,任何時候SQL中的任何匹配都可以完成,那麼所有的記錄都會返回 – 2012-03-07 01:59:41

1

這會給你比[Age][email protected] OR @AgeVar IS NULL方法更好的性能,因爲它會生成索引而不是試圖索引掃描:

SELECT * FROM [Table1] 
WHERE COALESCE(@AgeVar, Age) = Age 

它讓你的代碼非常易讀的,尤其是當你有多個參數你可能會或可能不會使用搜索,並仍然給你合理的表現。