[英]SQL Server 2008 - Conditional Query
SQL不是我的強項之一。 我有一個SQL Server 2008數據庫。 此數據庫具有一個存儲過程,該過程接收八個int參數。 為了保持這個問題的重點,我將使用這些參數之一作為參考:
@isActive int
這些int參數中的每一個都是-1,0或1. -1表示“未知”或“不關心”。 基本上,我需要查詢一個表,如果int參數是非-1,我需要在我的WHERE子句中考慮它。 因為有8個int參數,所以IF-ELSE語句似乎不是一個好主意。 與此同時,我不知道怎么做呢?
如果參數不等於值,在SQL中是否有一種優雅的方式來添加WHERE條件?
謝謝!
動態搜索條件的最佳來源:
Erland Sommarskog在T-SQL中的動態搜索條件
如果可以使用索引,對於如何執行此操作有很多微妙的含義。 如果您使用的是SQL Server 2008的正確版本,則只需向查詢添加OPTION (RECOMPILE)
,並在運行時將局部變量的值用於優化。
考慮到這一點, OPTION (RECOMPILE)
將采用此代碼(其中沒有索引可用於此混亂的OR
):
WHERE
(@search1 IS NULL or Column1=@Search1)
AND (@search2 IS NULL or Column2=@Search2)
AND (@search3 IS NULL or Column3=@Search3)
並在運行時優化它(假設只有@ Search2傳入一個值):
WHERE
Column2=@Search2
並且可以使用索引(如果在Column2上定義了一個索引)
WHERE coalesce(active,1) = (CASE
WHEN @isActive = -1 THEN coalesce(active,1)
ELSE @isActive
END)
模式(column = @param OR @param IS NULL)
將為您提供可選參數。 您可以使用NULLIF
來中和您的-1
。 更好的是允許空參數,而不是使用幻數 。
WHERE
(Customer.IsActive = NULLIF(@isActive, -1) OR NULLIF(@isActive, -1) IS NULL)
而不是使用-1表示你不知道或不關心,如何只使用Null? 幾乎就是為它做的。 然后你可以切換到Bit而不是Int。
另外,我確信TomTom會不同意,但我認為使用CASE語句是實現這一目標的方法。
您的里程可能會有所不同,但似乎查詢引擎處理它比在IsNull中包裝內容或具有多個OR語句要好得多,當您開始添加其他條件時,這可能會變得相當混亂。
無論你走哪條路,執行計划都會受到影響,具體取決於你傳遞的內容,但它不應該太糟糕了。
使用CASE語句的額外好處是,您可以添加一些復雜性而無需額外的代碼(與一堆OR語句相比)。 此外,匹配您的標准的第一個條件可以阻止額外的評估,這在處理OR時並非總是如此......
因此,對於8個可選參數,使用-1作為忽略搜索的值,最終得到的結果是:
WHERE
@Search1 = CASE WHEN @Search1 = -1 THEN @Search1 ELSE @Column1 END
AND @Search2 = CASE WHEN @Search2 = -1 THEN @Search1 ELSE @Column2 END
AND @Search3 = CASE WHEN @Search3 = -1 THEN @Search1 ELSE @Column3 END
AND @Search4 = CASE WHEN @Search4 = -1 THEN @Search1 ELSE @Column4 END
AND @Search5 = CASE WHEN @Search5 = -1 THEN @Search1 ELSE @Column5 END
AND @Search6 = CASE WHEN @Search6 = -1 THEN @Search1 ELSE @Column6 END
AND @Search7 = CASE WHEN @Search7 = -1 THEN @Search1 ELSE @Column7 END
AND @Search8 = CASE WHEN @Search8 = -1 THEN @Search1 ELSE @Column8 END
注意:正如KM指出的那樣,如果您正在使用的列可能具有NULL值,則NULL方法不足,因為NULL = NULL將無法正確評估。 所以,為了好玩,我把答案改回原來的海報要求的內容,即使用自己的標識符來跳過搜索。
.... Where field=case @isActive WHEN -1 THEN field ELSE @isActive END ....
沒有一種優雅的方式 - 所有方式都很糟糕。
WHERE @isActive == -1 OR isActive = @isActive
基本上是唯一的方法 - 但即便如此,請確保每次都重新評估查詢計划,否則大多數查詢將使用錯誤的查詢計划。
這是存儲過程不好的經典案例。 查詢是否應該使用存儲過程來完成恕我直言,因為現代 - 大約15年前,當有人足夠聰明地編寫第一個ORM時開始。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.