2011-09-23 102 views
3

我有一個返回數據的存儲過程。 。有條件的where子句T-SQL

我需要改變基礎上傳遞的參數的where子句

例如,參數爲:

@Region NVARHCAR(15) 
@CountryCode NVARCHAR(2) 
@ProductA BIT 
@ProductB BIT 
@ProductC BIT 

如果@region傳入,那麼這裏應該由區域選擇,如果@CountryCode通過,那麼應該按國家代碼選擇。

對於產品,如果它們中的任何一個設置爲true,則應在哪裏選擇該項目的數據。

這樣的聲明看起來是這樣的,如果@region在傳遞和@ProductA和@ProductC設置爲true:

SELECT * 
FROM table 
WHERE Region = @Region AND 
(Product = 'ProductA' OR Product = 'ProductC') 

另外,該產品的條件可能是一個報表。

如果@CountryCode傳遞在它看起來如下:

SELECT * 
FROM table 
WHERE CountryCode = @CountryCode AND 
(Product = 'ProductA' OR Product = 'ProductC') 

是@CountryCode和@region可能被傳入它甚至可以

有什麼辦法有T做到這一點-SQL,而不是從應用程序生成的動態SQL?

感謝

+3

有關此主題的權威性文章,請參閱[T-SQL中的動態搜索條件](http://www.sommarskog.se/dyn-search.html)。 –

+1

處理此問題的最常見的通用方法是查詢示例(http://en.wikipedia.org/wiki/Query_by_Example) – dkretz

回答

2

您可以使用條件始終生成SQL語句作爲字符串..然後簡單地使用sp_executesql執行結果語句字符串(命令它基本上執行一個Transact-SQL語句或可以重複使用多次的批處理,或者是一個動態構建的)...

我知道你可能不想構建sql字符串,但它是一個解決方案。

+0

我會嘗試這個,似乎是唯一不涉及一大堆if語句。 – Tom

2

這不一定是最乾淨的方法,但會避免任何動態:

SELECT * 
FROM table 
WHERE CountryCode = isnull(@CountryCode, CountryCode) AND 
Region = isnull(@Region, Region) AND 
(Product = 'ProductA' OR Product = 'ProductC') 
+0

玩這個我回來的是一個NULL行。我想我需要使用'sp_executesql' – Tom

+0

假設國家代碼或地區參數是NULL,如果它不包括那麼這種方法肯定會工作... – Timbo

6

你並不需要建立一個動態的SQL語句,你只需要檢查的值的參數。下面是我常用構建SQL條款來實現這一點:

WHERE ((@Region IS NULL) OR (Region = @Region)) 
AND ((@CountryCode IS NULL) OR (CountryCode = @CountryCode)) 
AND ((@ProductA = 0) OR (Product = 'ProductA')) 
AND ((@ProductB = 0) OR (Product = 'ProductB')) 
AND ((@ProductC = 0) OR (Product = 'ProductC')) 

如果你的SQL是建立這樣,那麼你只過濾在地區列,當你在爲@region參數的值傳遞。 CountryCode也是如此。

+0

玩這個我回來的是一個NULL行。 – Tom

+1

@Tom我無法爲您做調試。我建議一次解決這個參數。你是否在@Region傳遞NULL值?如果是這樣,那麼你不應該按該欄過濾。如果您確實傳入了一個值,則只會返回與您傳入的值相匹配的記錄。 –

+0

我想我有正確的構建:http://notepad.cc/mamuge32 – Tom

2

我會簡化併爲每個案例編寫一個存儲過程。或者至少添加程序邏輯:

IF NOT @region IS NULL ....

,並有單獨的查詢,可以對自己的優點進行優化。

編輯:

A couple principles that I think apply: 

http://en.wikipedia.org/wiki/Coupling_%28computer_programming

http://en.wikipedia.org/wiki/Single_responsibility_principle

+1

OP給出的條件已經非常簡單。對於每種情況,單獨的存儲過程聽起來像對我來說過大。 –

+2

@ Ek0nomik - 捕捉所有查詢的問題是,執行計劃吸(雖然'重新編譯提示可以幫助) –

+0

這一定會工作,但我試圖避免它,因爲會有很多ifs的數量可用條件。 – Tom

0

我會用一個公共表表達式

+2

CTE如何幫助這裏? – Lucero

1

如果有的話,最直接的方法(並不一定是最優雅的)是設置每個參數的缺省值是不是有效的參數值和執行有條件地檢查每個參數是否包含在每個參數中的值與默認值不同。這裏我假定空值永遠不會作爲有效值傳入。

CREATE PROC sp_ProdInfo (
@Region NVARHCAR(15) = NULL, 
@CountryCode NVARCHAR(2) = NULL, 
@ProductA BIT, 
@ProductB BIT, 
@ProductC BIT 
) 
AS 
BEGIN 
-- other statements 
IF NOT @Region IS NULL 
    BEGIN 
    SELECT * 
    FROM table 
    WHERE Region = @Region AND 
    (Product = 'ProductA' OR Product = 'ProductC') 
    END 
ELSE 
    BEGIN 
    IF NOT @Country IS NULL 
    BEGIN 
    SELECT * 
    FROM table 
    WHERE CountryCode = @CountryCode AND 
    (Product = 'ProductA' OR Product = 'ProductC') 
    END 
    ELSE 
    BEGIN 
    PRINT 'Neither Country nor Region was passed in.' 
    END -- end inner if 
    END -- end outer if 
-- other statements 
END