2013-07-23 61 views
2

我正在創建一個報告工具,用戶可以在其中選擇運算符和2個值進行篩選。T-SQL:使用動態比較運算符的篩選器(=,<=, > =,...)

我的基本表:

UserID  UserName 
------------------------------- 
1   User1 
2   User2 
3   User3 
4   User4 
5   User5 

用戶可以選擇,我想翻譯這樣操作:

Option  SQL Operator 
------------------------------ 
between   column between x and y 
like   column '%' + x + '%' 
greater than column > x 
less than  column < x 
equal to  column = x 
not equal to column <> x 

我想類似的東西:

... column = ISNULL(@parameter, column) 

從某種意義上說,如果你傳遞了一些東西或什麼都沒有,它仍然會正確地查詢。

下面是我用打TSQL(**不起作用*):

declare @bwValue1 varchar(200) = '2', --between value 1 
@bwValue2 varchar(200) = '4'; --between value 2 

select * from users where 
(UserID BETWEEN @bwValue1 AND @bwValue2 
OR UserID != @bwValue1 
OR UserID = @bwValue1 
OR UserID < @bwValue1 
OR UserID > @bwValue1 
OR UserID LIKE '%' + @bwValue1 + '%'); 

有沒有寫一個TSQL能夠正確評估語句無論選擇哪個運營商的方式?

*最終答案*

這裏是我結束了對任何人是好奇:

declare @fn varchar(200) = 'carl', 
    @Op varchar(3) = 'bw', 
    @bwValue1 varchar(200) = '978', 
    @bwValue2 varchar(200) = '2000' 

select * from users where userfirstname like '%' + @fn + '%' 
     AND ((@Op = 'eq' AND (userid = @bwValue1)) 
OR (@Op = 'neq' AND (userid <> @bwValue1)) 
OR (@Op = 'lt' AND (userid < @bwValue1)) 
OR (@Op = 'gt' AND (userid > @bwValue1)) 
OR (@Op = 'li' AND (userid like '%' + @bwValue1 + '%')) 
OR (@Op = 'bw' AND (userid between @bwValue1 and @bwValue2))) 
+0

根據指定參數構建動態SQL。 –

+0

是的,我試圖避免這樣做。要求說我應該使用「參數化SQL」,以便sql可以緩存sp以供將來使用,執行計劃等。 – Losbear

+0

我不認爲有這麼多不同的參數,SQL可以創建一個正常穩定的計劃,場景。 –

回答

7

動態SQL並不意味着你不能將其參數化和緩存的計劃。工作得很好,因爲SQL Server無法區分差異。如果您的應用連接了幾個SQL字符串(不包含動態字面量!),SQL Server會像處理其他任何查詢一樣對待它們。它緩存了這個計劃。當然,每個運營商都會產生不同的計劃。也許這就是你想要的,如果查詢可以在索引上尋找這種方式!

所以我建議你使查詢靜態除了運營商。

如果你不能做到這一點,願意放棄對SARGability,這樣做:

WHERE 0=0 
OR (Operator = '=' AND (A = B)) 
OR (Operator = '<' AND (A < B)) 
OR (Operator = '>' AND (A > B)) 
---... 

完全OR條款就會變得「活躍」在運行時。它仍然看起來可讀和可維護。

+0

BETWEEN有點麻煩。但是這與[我的答案在這裏]類似(http://stackoverflow.com/questions/10703072/passing-an-operand-as-an-sql-parameter)。 –

+1

是的 - 這正是我正在尋找的 - 謝謝你! – Losbear

+0

你節省了我的一天..在使用OR之前,最好設置一個AND cond。或者(運算符='<'AND (A B)) –

0

我已經完成的一個便宜的方法是通過使用布爾比較器來指定我想要的比較。

WHERE (A = B AND @equalOp = 1) OR (A > B AND @gtOp = 1) OR (A < B AND @ltOp = 1) 

簡單,甚至不需要動態SQL。查詢優化器應該防止通過使用布爾值來最大限度地減少查詢發生實際比較。我會仔細檢查一下,但它對我來說很有幫助!

+0

謝謝,那簡直太愚蠢了:)今天已經在六種語言之間切換了。 – Codeman