2011-05-16 80 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'接受参数,因此您可以直接将您的参数传递给此查询,以便实习生重用您的执行计划。

动态查询并不总是坏的性能特别是当你适当地使用它

相关问题