2011-05-16 25 views
2

我需要創建一個需要12個參數的存儲過程,並使用此參數的不同組合過濾查詢。所有12個參數都不是強制性的,就像我傳遞3或5或12個參數一樣,取決於用戶輸入的搜索輸入。什麼是更好的,動態SQL還是在哪裏?

我可以創建2種方式,或者使用動態SQL查詢或使用「情況」語句。這些查詢的例子是如下:

  1. 動態查詢

    DECLARE @sql VARCHAR(MAX) 
    DECLARE @condition VARCHAR(MAX)='' 
    Declare @var1 varchar(10) 
    Declare @var2 varchar(10) 
    Declare @var3 varchar(10) 
    SET @sql='SELECT * FROM TableDemo1 TD1 WITH(NOLOCK) 
    INNER JOIN TableDemo2 TD2 ON TD1.Column1=TD2.Column2' 
    if(@var1 <>0 and @var1 is not null) 
    begin 
        if(@condition<>'') 
        begin 
         set @[email protected] + ' and TD1.columnTest1='[email protected]) 
        end 
        else 
        begin 
         set @condition=' where TD1.columnTest1='[email protected] 
        end 
    end 
    if(@var2 <>0 and @var2 is not null) 
    begin 
        if(@condition<>'') 
        begin 
         set @[email protected] + ' and TD2.columnTest2='[email protected]) 
        end 
        else 
        begin 
         set @condition=' where TD2.columnTest2='[email protected] 
        end 
    end 
    
    if(@var3 <>0 and @var3 is not null) 
    begin 
        if(@condition<>'') 
        begin 
         set @[email protected] + ' and TD1.columnTest3='[email protected]) 
        end 
        else 
        begin 
         set @condition=' where TD1.columnTest3='[email protected] 
        end 
    end 
    SET @[email protected][email protected] 
    EXEC(@sql) 
    
  2. 查詢使用情況

    Declare @var1 varchar(10) 
    Declare @var2 varchar(10) 
    Declare @var3 varchar(10) 
    SELECT * 
    FROM TableDemo1 TD1 WITH(NOLOCK) 
        INNER JOIN TableDemo2 TD2 ON TD1.Column1=TD2.Column2 
    WHERE 
        (CASE WHEN 
        (@var1<>0 and @var1 is not null) 
        THEN 
        CASE WHEN [email protected] THEN 1 ELSE 0 END 
        ELSE 1 END)=1 
        AND 
        (CASE WHEN 
        (@var2<>0 and @var2 is not null) 
        THEN 
        CASE WHEN [email protected] THEN 1 ELSE 0 END 
        ELSE 1 END)=1 
        AND 
        (CASE WHEN 
        (@var3<>0 AND @var3 IS NOT NULL) 
        THEN 
        CASE WHEN TD1.columnTest3 = @var3 
        THEN 1 ELSE 0 END 
        ELSE 1 END) =1 
    

這只是我的存儲過程的一部分,有具有連接的7-8個表格以及如上查詢條件中的各種情況。

如果我使用一個動態查詢,SQL Server將要創建一個執行計劃每一次,但如果我用「情況」這也使得查詢慢。

我知道動態SQL的缺點,但我應該使用哪種技術?

+0

注意'@var <> 0 AND @var IS NOT NULL'僅相當於'@var <> 0'。 – 2011-05-16 15:01:30

回答

2

通常它取決於,但大多數情況下我使用動態查詢作爲最後的手段。關於您的問題,我很可能會使用CASE解決方案,但我認爲您的CASE表達式不必要的複雜。我會像這樣的東西替換WHERE子句:

... 
WHERE 
    TD1.columnTest1 = COALESCE(NULLIF(@var1, 0), TD1.columnTest1) 
    AND 
    TD2.columnTest2 = COALESCE(NULLIF(@var2, 0), TD2.columnTest2) 
    AND 
    TD1.columnTest3 = COALESCE(NULLIF(@var3, 0), TD1.columnTest3) 

有了適當的索引這應該不會太慢。

+0

這是非常簡單的方法,但它會給出錯誤,但是在沒有大小寫的情況下工作時,像這樣「WHERE TD1.columnTest1 = COALESCE(@ var1,1.columnTest1)」,但它想要抵制'0'值,你能幫忙嗎?我如何在這裏使用索引? – sam11 2011-05-17 05:24:55

+0

@ user737529:我不敢相信我會把它留在這裏!我現在試着重寫它。謝謝你的提示! – 2011-05-17 05:26:39

+0

@ user737529:你在。現在它應該將NULL與NULL相同。 – 2011-05-17 05:29:06

3

以我的經驗動態where條款提供更好的性能。特別是在大型數據集上。

和非常好的解釋是Catch All Queries

3

動態查詢將導致索引掃描。

的情況下將導致SEQ掃描(即讀取整個表)。

所以一定要去動態查詢。

0

我已經使用了選項「舍甫琴科M」使用聚結和NULLIF函數公佈。

但是這個選項只適用'='操作符,但要找到如何在其他條件下使用它,一個例子是使用'IN'關鍵字。

TD1.columnTest1 = (
    CASE 
     WHEN (
      (TD1.columnTest1 
       IN (
        SELECT item FROM dbo.Splitfunction(@comaSepValues,',') 
       ) 
      ) 
      OR 
      NULLIF(@PlaceTypeCode,'') IS NULL 
     ) THEN columnTest1 
     ELSE NULL 
    END 
) 

讓我知道這是否有效。

+0

請考慮發佈新問題。如果你確實發佈了它,請刪除這個答案。 – 2011-05-18 14:04:17

0

有執行動態查詢 1. Exec的 2. sp_executesql的

如果你想重用你的執行計劃,然後去sp_executesql的選項

兩種方式。

'SP_ExecuteSQL'接受參數,因此您可以直接將您的參數傳遞給此查詢,以便實習生重用您的執行計劃。

動態查詢並不總是壞的性能特別是當你適當地使用它

相關問題