【问题标题】:SQL: building a filter - can this be done without dynamic sql?SQL:构建过滤器 - 可以在没有动态 sql 的情况下完成吗?
【发布时间】:2011-07-08 01:15:22
【问题描述】:

这是我在我们制作的列表中一直看到的。 必须为 2 列做一个过滤器(我举了一个较短的例子,我们有 50 列的列表,看起来一样...)

我想知道是否有办法以某种不同的方式做到这一点。 你们用什么来过滤表中的记录?

    /* parameters */
@CostNumber = ...
@Description = ...
    /* parameters */

SET @strSQL = '
SELECT  [CostLevelId], [CostNumber], [Description]
FROM    [CostLevel]
WHERE   1 = 1 ' /* this looks weird, but we'll add the "WHERE" stuff easier */

IF (@CostNumber IS NOT NULL)
BEGIN
    SET @strSQL = @strSQL + ' AND [CostNumber] LIKE ''%' + REPLACE(@CostNumber,'''','''''') + '%'' '
END

IF (@Description IS NOT NULL)
BEGIN
    SET @strSQL = @strSQL + ' AND [Description] LIKE ''%' + REPLACE(@Description,'''','''''') + '%'' '
END

EXEC (@strSQL)

【问题讨论】:

    标签: sql sql-server-2005 filter dynamic-sql


    【解决方案1】:

    为什么不放弃动态 SQL 方法?

        /* parameters */
    @CostNumber = ...
    @Description = ...
        /* parameters */
    
    SELECT  [CostLevelId], [CostNumber], [Description]
    FROM    [CostLevel]
    WHERE   [CostNumber] LIKE '%' + @CostNumber + '%'
    AND [Description] LIKE '%' + @Description + '%'
    

    需要注意的几件事 - @CostNumber 和 @Description 参数中的 nulls - 您必须确保将它们转换为空字符串。

    您需要考虑的另一件事是@Description might 包含% 字符,您必须将其转义才能使LIKE 正常工作。

    【讨论】:

      【解决方案2】:

      当涉及LIKE 运算符时,我不知道该怎么做,当使用比较运算符时,我使用默认值来获得类似这样的东西:

      select *
      from dbo.SomeTable a
      where
      (a.IntColumn = @IntColumnValue or @IntColumnValue = -1)
      and (a.VarCharColumn = @VarCharValue or @VarCharValue = 'zzz')
      

      这样,如果我不想应用特定过滤器,我只需将其设置为默认值(在此示例中为 -1 或 zzz),因此其检查始终为 true。

      使用LIKE 运算符应该类似,也许您应该将默认值设置为您知道永远不会在数据中找到的某种字符串?像这样?

      where (a.VarCharColumn like '%' + @VarCharValue + '%' or @VarCharValue = '§§§TheDefaultValue§§§')
      

      【讨论】:

        【解决方案3】:

        我没有办法测试这个atm,但是怎么样

        SELECT  [CostLevelId], [CostNumber], [Description]
        FROM [CostLevel]
        WHERE (@CostNumber IS NOT NULL AND [CostNumber] LIKE ''%' + REPLACE(@CostNumber,'''','''''') + '%'')
        OR
        (@Description IS NOT NULL AND [Description] LIKE ''%' + REPLACE(@Description,'''','''''') + '%'')
        GROUP BY [CostLevelId], [CostNumber], [Description]
        

        如果做不到这一点,您可以尝试使用 UNION 而不是 OR(和分组)。

        【讨论】:

          【解决方案4】:

          您可以测试查询中的值是否为 null,再加上您的条件和允许可选参数的 or 语句。

          这适用于 like 语句。

          SELECT  [CostLevelId], [CostNumber], [Description]
          FROM    [CostLevel]
          WHERE   
              (@CostNumber is null or [CostNumber] LIKE '%'+@CostNumber+'%')
              and
              (@Description is null or [Description] LIKE '%'+@Description+'%')
          

          如果是直接相等比较,您可以使用 coalesce 与填充的变量进行比较,或者当变量为空时,与自身进行比较。

          SELECT  [CostLevelId], [CostNumber], [Description]
          FROM    [CostLevel]
          WHERE   
              [CostNumber] = coalesce(@CostNumber,[CostNumber])
              and
              [Description] = coalesce(@Description,[CostNumber])
          

          请记住,这可能会对您的查询计划产生不利影响,具体取决于设置的变量、表填充和数据库结构等。您甚至可能会发现动态 sql 方法的执行效率比这更高,尽管在它的构造。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2021-05-29
            • 2016-08-28
            • 1970-01-01
            • 2021-01-24
            • 1970-01-01
            • 2011-06-30
            • 1970-01-01
            相关资源
            最近更新 更多