2009-07-08 18 views
1

這是Slow Exists Check的續作。亞歷克斯的建議工作,併成功地避免代碼重複,但我仍然結束了第二個問題。考慮下面的例子(來自AlexKuznetsov)。其中,我有兩個分支來處理1次違禁。如果我有兩個可選的約束條件,我最終會得到4個分支。基本上,分支的數量隨着約束的數量呈指數增長。另一方面,如果我使用多語句表值函數或使用臨時表,SQL查詢優化器不能幫助我,所以事情變得緩慢。我對動態SQL有些不信任(我也聽說它也很慢)。有效處理Where子句中的多個可選約束條件

任何人都可以提供有關如何添加更多約束而不添加大量if語句的建議?

說明:我以前試過把x is null or inpo = @inpo連在一起,但是這個很慢。請記住,雖然inpo = @inpo測試可以通過某種索引黑魔法來處理,但無效測試最終將針對表中的每一行進行評估。

IF @inpo IS NULL BEGIN 
    SELECT a,b,c 
    FROM dbo.ReuseMyQuery(@i1) 
    ORDER BY c; 
END ELSE BEGIN 
    SELECT a,b,c 
    FROM dbo.ReuseMyQuery(@i1) 
    WHERE inpo = @inpo 
    ORDER BY c; 
END 

變化二:2約束:

IF @inpo IS NULL BEGIN  
    IF @inpo2 IS NULL BEGIN 
     SELECT a,b,c 
     FROM dbo.ReuseMyQuery(@i1) 
     ORDER BY c; 
    END ELSE BEGIN 
     SELECT a,b,c 
     FROM dbo.ReuseMyQuery(@i1) 
     WHERE inpo2 = @inpo2 
     ORDER BY c; 
    END 
END ELSE BEGIN 
    IF @inpo2 IS NULL BEGIN 
     SELECT a,b,c 
     FROM dbo.ReuseMyQuery(@i1) 
     WHERE inpo = @inpo 
     ORDER BY c; 
    END ELSE BEGIN 
     SELECT a,b,c 
     FROM dbo.ReuseMyQuery(@i1) 
     WHERE inpo = @inpo AND 
       inpo2 = @inpo2 
     ORDER BY c; 
    END 
END 

回答

0
Select blah from foo  
Where (@inpo1 is null or @inpo1 = inpo1) 
and (@inpo2 is null or @inpo2 = inpo2) 

顯然,這是太慢了。有趣。

您是否考慮過代碼生成?如果需要直接維護,冗長的重複查詢只是一個問題。

+0

正如我在慢存在檢查中所述,該解決方案很慢。 – Brian 2009-07-08 21:31:50

0

下面是一個粗略的例子。根據您希望查詢中的「開始於」或「包含」或完全匹配,修改WHERE子句中的LIKE語句。

CREATE PROCEDURE dbo.test 
@name  AS VARCHAR(50) = NULL, 
@address1  AS VARCHAR(50) = NULL, 
@address2  AS VARCHAR(50) = NULL, 
@city  AS VARCHAR(50) = NULL, 
@state  AS VARCHAR(50) = NULL, 
@zip_code  AS VARCHAR(50) = NULL 
AS 

BEGIN 

SELECT [name], 
      address1, 
      address2, 
      city, 
      state, 
      zip_code 
FROM my_table 
WHERE ([name] LIKE @name + '%' OR @name IS NULL) 
      AND (address1 LIKE @address1 + '%' OR @address1 IS NULL) 
      AND (address2 LIKE @address2 + '%' OR @address2 IS NULL) 
      AND (city LIKE @city + '%' OR @city IS NULL) 
      AND (state LIKE @state + '%' OR @state IS NULL) 
      AND (zip_code LIKE @zip_code + '%' OR @zip_code IS NULL) 
ORDER BY [name] 
END 
GO 
+0

我以前試過這個(在最初的問題中提到過)。它很慢。 – Brian 2009-07-08 21:34:17

0

我明白你的問題可能是純學術性的,但如果你有真正的使用案例你有沒有考慮只對最常見的情況,提供優化的查詢?

+0

我認爲這是一種解決方案,但考慮一下可以使用的東西,如果我沒有選擇而不是理想。 – Brian 2009-07-09 13:55:08

1

在這種情況下,我使用sp_executesql在厄蘭的文章中描述:Using sp_executesql 無論何時使用動態SQL,缺少權限可能是一個問題,所以我有一個單元測試真正的網絡帳戶,我該帳戶添加到實際作用,並且在我測試動態SQL時,我會模仿這個真實賬戶,如下所述:Database Unit Testing: Impersonation