SQL - WHERE中的CASE表达式

时间:2009-01-05 20:39:13

标签: sql where-clause

我在这里阅读了有关在WHERE子句中使用CASE表达式的内容:

http://scottelkin.com/sql/using-a-case-statement-in-a-sql-where-clause/

我正在尝试使用它来根据用户应用程序传递的合同号来过滤select语句的结果。我的代码当前抛出了'无效参数'的错误,无论传入什么。我验证SELECT / FROM工作正常,如没有CASE表达式的WHERE子句。这是我的代码。

WHERE     (CASE WHEN @ContractNo = 0 THEN @ContractNo ELSE @ContractNo END =
tblContracts.ContractNo)

代码的冗余用于故障排除,我打算稍后在CASE上使用通配符过滤。我正专注于立即降低语法。我相信这应该返回参数与表中存储的合同号匹配的所有记录。任何帮助或建议将不胜感激。

12 个答案:

答案 0 :(得分:9)

你确定要这么做吗?您的案例陈述总是返回@ContractNo。我认为你在寻找的是:

where 
    case @ContractNo 
        when 0 then tblContracts.ContractNo 
        else @ContractNo 
    end = tblContracts.ContractNo

上面的过滤器显示“给我ContractNo等于参数的合同,或者如果参数为0,则为所有合同。

仅过滤合约编号字段与参数完全相同的前一过滤器。

无论如何,你应该这样做:

where @ContractNo = 0 or @ContractNo = tblContracts.ContractNo

逻辑更容易理解,除此之外(不要引用我),优化器可能会在case语句之外更好地工作。

答案 1 :(得分:7)

阅读完解释后,有一种更好的方法可以在没有CASE的情况下执行此操作:

WHERE @ContractNo = 0 OR tblContracts.ContractNo = @ContractNo

这将只返回匹配的合同号,除非@ContractNo为0,在这种情况下它将返回所有记录。

编辑:我刚刚注意到casperOne proposed the same thing。我没有看到。大自己。

答案 2 :(得分:2)

尽量忽略错误位置的括号 - 正确的括号应该在“结束”之后。

答案 3 :(得分:2)

也许你忘了宣布@ContractNo?它是否与0和tblContracts.ContractNo?

相当

答案 4 :(得分:1)

将你的右括号移到=之前,如下所示:

WHERE     (CASE WHEN @ContractNo = 0 THEN @ContractNo ELSE @ContractNo END)=tblContracts.ContractNo

我没看到这个案例陈述会做什么但是......如果@ContractNo = 0或者它不是......那么你将返回相同的东西......

正确的语法是:

  Select...
  ...
  Where(
    Case
      When <Condition>
        Then <Return if true>
        Else <Return if false>
      End
 ) = <Whatever is being matched to the output of the case statement>

无论语法如何,你的例子没有多大意义,如果你正在寻找所有匹配或者合同号为0的项目,那么你会这样做:

Select...
...
Where (
  @ContractNo = 0 Or
  @ContractNo = tblContracts.ContractNo
)

这似乎比你试图使用case语句更有意义。

编辑:我一定是误解了这个问题 - 缺少的参数通常意味着参数(在本例中为@ContractNo)未在查询/过程的范围内声明。但有人已经指出了这一点,所以我不能相信这一点。

答案 5 :(得分:1)

case语句的原因,包括整个“If it为0,给出参数,否则,只给出参数”是为了测试它以试图使语法正确。最初,我试过说“如果它是0,然后传入'%',返回每个值。我在那里发布的代码是因为我一直得到'无效参数'并且认为我的语法一定有问题。我将它分成基本参数匹配,如此,

WHERE @ContractNo = tblContracts.ContractNo

它恢复了记录。让我解释一下。

我从一堆不同的表中提取,并使用未包含在select语句中的信息过滤内容(即tblContracts没有通过Select从中提取信息,它仅在Where中使用)。用户将从具有不同合同号的组合框中进行选择,以及默认值“全部”。

当组合框的索引发生变化时,我将发生一个事件。如果它是'All',0将作为参数传入,我不想进行过滤。否则,我只想要该合同号的信息(Else @ContractNo的原因)。

答案 6 :(得分:1)

Recursive的帖子正好解决了我的问题。

我看到有关我原帖的清晰度的投诉。在未来,我能做些什么才能让我说的更直接?我不习惯于对代码的问题进行措辞,并为任何混乱的事情道歉。我是否只需要在第二篇文章中提供扩展的详细信息?

再次感谢您的帮助。

答案 7 :(得分:0)

你的意思不是这样的吗?

SELECT * 
    FROM tblContracts
    WHERE     
    CASE 
       WHEN tblContracts.ContractNo = 0 THEN @ContractNo 
       ELSE tblContracts.ContractNo
    END = tblContracts.ContractNo

其中@ContractNo是与tblContracts.ContractNo相同的数据类型的变量

答案 8 :(得分:0)

为什么你甚至需要一个案例陈述?

当@ContractNo = 0然后(0 = tblContracts.ContractNo) 否则@ContractNo(@ContractNo = tblContracts.ContractNo)

这没有任何意义,因为您可以简单地将其写为

其中@contractNo = tblContracts.contractNo

答案 9 :(得分:0)

合约编号实际上是数字还是字符串总是恰好是数字。检查表与参数和CASE语句之间的数据类型(例如,“= 0”或“='0'”)

答案 10 :(得分:0)

此语法应该有效(在Oracle中有效)

WHERE CASE WHEN tblContracts.ContractNo = 0 
           THEN @ContractNo 
           ELSE tblContracts.ContractNo
      END = tblContracts.ContractNo

答案 11 :(得分:0)

当你说:

  

我从一堆不同的表中提取,并使用未包含在select语句中的信息过滤内容(即tblContracts没有通过Select从中提取信息,它仅在Where中使用)。用户将从具有不同合同号的组合框中进行选择,以及默认值“全部”。

然后我觉得应该有一个“Where exists”条款。既然你没有从那张桌子中取出任何信息?!