【问题标题】:T-SQL Where int=@var / @var=null?T-SQL 哪里 int=@var / @var=null?
【发布时间】:2012-03-12 00:46:04
【问题描述】:

我遇到了调用存储过程并传入一些变量的情况。在某些情况下,我会传入 null 并且我希望它返回所有内容。采取以下(年龄是一个整数列):

[Table]  
[Name] | [Age]  
Mike   | 22  
Fred   | 18  
Bob    | 22 



SELECT * FROM [table] WHERE [Age]=@AgeVar

现在如果我通过 22,我会得到 Mike 和 Bob。同样,通过 18 会得到 Fred。但是,如果我在传入 null/不设置 @AgeVar 时想要所有 3 行怎么办?这是我的一个非常简单的问题。

编辑:Sproc 非常复杂,我真的不想通过将所有部分加倍,但它们是以下答案之一的两倍。还有其他方法吗?

【问题讨论】:

  • 如果您没有时间点击 Joe 的链接,指向他非常出色的文章,他证明使用动态 SQL 可能会比这种方法更好。
  • @DOK: 澄清一下,我不是这篇文章的作者。那篇文章是 Gail Shaw 写的,他在 SQL Server 方面比我聪明得多。
  • @Joe Stefanelli,我们都站在巨人的肩膀上,不是吗?
  • 请停止在您的帖子上签名。

标签: sql sql-server tsql null integer


【解决方案1】:
SELECT * FROM [table] WHERE [Age]=@AgeVar OR @AgeVar IS NULL

正如上面和下面多次提到的,这种技术会降低您对大型表的查询的性能。用户小心。

【讨论】:

  • 这是一个绝妙的答案。从来没有想过这样做。杰出的。我会在稍后将其标记为答案,因为它说我必须做什么。但是谢谢!!
  • 仅供参考...这对 SqlServer 中的查询执行计划造成严重破坏...由于上述查询,我​​们最近不得不重构一堆 SPROC。
  • @EoinCampbell:这就是我在对该问题的评论中引用的博文的重点。
  • 是的,这是一个解决方案,但它绝对是性能杀手。但是,无论如何,当需求指定此行为时,您的选择是有限的。在将报表绑定到单个查询或存储过程时尤其如此。
  • 说实话,我认为性能杀手更多的是数据库设计。此查询可能无济于事,但我相当有信心解决我的问题,这将使这种样式查询的需求消失:(。最好了解有关数据库设计和索引的更多信息..
【解决方案2】:
IF @AgeVar IS NULL 
    BEGIN
        SELECT  *
        FROM    @Table
    END
ELSE
    BEGIN
        SELECT  *
        FROM    @Table
        WHERE   Age = @AgeVar
    END

【讨论】:

  • 是的,我正在考虑这样的事情,但我正在执行此操作的存储过程非常庞大,并且真的不想为此将每个部分分成两部分。有没有其他办法?
  • 已经发布的OR 选项会起作用,WHERE ISNULL(@AgeVar, [Age]) = [Age] 也会起作用。但是,优化器可以更好地处理上面发布的选项。您可以考虑创建一个临时表,使用 IF ... ELSE 填充它,然后在程序的后面部分引用它,但这可能会根据程序的其余部分和指标等而变得更糟。
  • 我会担心这个查询计划缓存。
  • 比起在 select 语句中使用不必要的谓词对性能的影响,我不太关心查询缓存。为了解决OP发布的问题,这是最有效的解决方案。如果需要更多变量,那么 SQL 注入可能是其他 cmets/文章中讨论的前进方向。
  • @GarethD 我认为您的意思是动态 SQL,而不是 SQL 注入。除非您的意图不那么光荣,并且 SQL 注入是给定的! :-)
【解决方案3】:

我发现如果你有一个常见的情况,那么使用 CASE 语句。这只会在极少数情况下造成性能拖累。因此,如果您更频繁地将 null 作为参数传递,那么这将更有效。

SELECT * 
FROM [table] 
WHERE 
    0 = 
        CASE 
            WHEN @AgeVar IS NULL THEN 0
            WHEN [Age]=@AgeVar THEN 0
        END

【讨论】:

  • 我还没有实际测试过这个,但在我看来这行不通:如果 [Age] = @AgeVar 那么最终查询将最终看起来像 select * from [table] where 0=0 ...你最终会得到所有的记录!
  • 我在许多情况下都使用它取得了巨大的成功。想想 SQL 是如何工作的,这应该是有道理的。它类似于存在。 select * from [table] where 0 = 0 仅发生在当前行的 [Age] 列等于 @AgeVar 的情况下。根据您的逻辑,只要在 SQL 中进行任何匹配,那么所有记录都会返回
【解决方案4】:

这将为您提供比[Age]=@AgeVar OR @AgeVar IS NULL 方法更好的性能,因为它会生成索引搜索而不是索引扫描:

SELECT * FROM [Table1]
WHERE COALESCE(@AgeVar, Age) = Age

它使您的代码具有相当的可读性,尤其是当您有多个参数可能会或可能不会用于搜索时,并且仍然可以为您提供合理的性能。

【讨论】:

    猜你喜欢
    • 2012-09-09
    • 2013-06-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-18
    • 1970-01-01
    • 2019-03-14
    • 2016-11-26
    相关资源
    最近更新 更多