什么是更好的动态SQL或者哪种情况?

时间:2011-05-16 11:07:54

标签: sql performance dynamic case where

我需要创建一个存储过程,该过程需要12个参数,并使用此参数的不同组合过滤查询。所有12个参数都不是强制性的,因为我传递3或5或12个参数取决于用户输入的搜索输入。

我可以创建两种方法,使用动态SQL查询或使用“Case where”语句。这些查询的示例如下:

  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 @condition=@condition + ' and TD1.columnTest1='+@var1)
        end
        else
        begin
            set @condition=' where TD1.columnTest1='+@var1
        end
    end
    if(@var2 <>0 and @var2 is not null)
    begin
        if(@condition<>'')
        begin
            set @condition=@condition + ' and TD2.columnTest2='+@var2)
        end
        else
        begin
            set @condition=' where TD2.columnTest2='+@var2
        end
    end
    
    if(@var3 <>0 and @var3 is not null)
    begin
        if(@condition<>'')
        begin
            set @condition=@condition + ' and TD1.columnTest3='+@var3)
        end
        else
        begin
            set @condition=' where TD1.columnTest3='+@var3
        end
    end
    SET @sql=@sql+@condition
    EXEC(@sql)
    
  2. 使用CASE WHERE查询

    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 TD1.columnTest1=@var1 THEN 1 ELSE 0 END  
        ELSE 1 END)=1  
      AND   
      (CASE WHEN  
        (@var2<>0 and @var2 is not null)   
        THEN  
        CASE WHEN TD2.columnTest2=@var2 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
    
  3. 这只是我的存储过程的一部分,有7-8个表连接,并且如上所述在查询中有各种条件。

    如果我使用动态查询,SQL Server每次都必须创建一个执行计划,但如果我使用'case where',它也会使查询变慢。

    我知道动态SQL的缺点,但我应该使用哪种技术?

5 个答案:

答案 0 :(得分:3)

根据我的经验,动态where子句提供了更好的性能。特别是在大型数据集上。

Catch All Queries中有一个非常好的解释。

答案 1 :(得分:3)

动态查询将导致索引扫描。

案例将导致seq扫描(即读取整个表格)。

所以一定要使用动态查询。

答案 2 :(得分: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)

通过适当的索引,这不应该太慢。

答案 3 :(得分:0)

我使用了使用coalesce和nullif函数发布的“Andriy M”选项。

但是此选项仅适用于'='运算符,但要找到如何将其与其他条件一起使用,一个示例是使用'IN'关键字。

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

让我知道这是否有效。

答案 4 :(得分:0)

执行动态查询有两种方法 1.执行 2. sp_executeSQL

如果要重用执行计划,请转到sp_executeSQL选项。

&#39; sp_executesql的&#39;接受参数,因此您可以直接将参数传递给此查询,该查询将实际重用您的执行计划。

动态查询的性能并不总是特别适合您正确使用