[英]SQL - CASE expression inside WHERE
我在这里阅读了有关在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上使用通配符过滤。 我正专注于立即降低语法。 我相信这应该返回参数与表中存储的合同号匹配的所有记录。 任何帮助或建议将不胜感激。
你确定你要这么做吗? 你的case语句总是返回@ContractNo
。 我认为你在寻找的是:
where
case @ContractNo
when 0 then tblContracts.ContractNo
else @ContractNo
end = tblContracts.ContractNo
上面的过滤器说“给我合同,其中ContractNo
等于参数,或者如果参数为0,则给出所有ContractNo
。
仅过滤合同编号字段与参数完全相等的前一过滤器。
无论如何,你应该这样做:
where @ContractNo = 0 or @ContractNo = tblContracts.ContractNo
逻辑更容易理解,除此之外(不要引用我),优化器可能会在case语句之外更好地工作。
阅读完解释后,有一种更好的方法可以在没有CASE
下执行此操作:
WHERE @ContractNo = 0 OR tblContracts.ContractNo = @ContractNo
这将仅返回匹配的合同号,除非@ContractNo
为0,在这种情况下,它将返回所有记录。
编辑:我刚刚注意到casperOne提出了同样的事情 。 我没有看到。 大自己。
试着省略错误位置的括号 - 正确的一个应该在“结束”之后。
也许你忘了宣布@ContractNo? 它是否与0和tblContracts.ContractNo相当?
将你的右括号移到=之前,如下所示:
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)未在查询/过程的范围内声明。 但是有人已经指出了这一点,所以我不能相信这一点。
case语句的原因,包括整个“If it为0,给出参数,否则,只给出参数”是为了测试它以试图使语法正确。 最初,我试过说“如果它是0,然后传入'%',返回每个值。我在那里发布的代码是因为我一直得到'无效参数'并且认为我的语法一定有问题。我把它分成基本的参数匹配,像这样,
WHERE @ContractNo = tblContracts.ContractNo
它返回记录很好。 让我解释一下。
我从一堆不同的表中提取,并使用select语句中未包含的信息过滤内容(即tblContracts没有通过Select从中提取信息,它仅在Where中使用)。 用户将从具有不同合同号的组合框中进行选择,以及默认值“全部”。
当组合框的索引发生变化时,我将发生一个事件。 如果它是'All',0将作为参数传入,我不想进行过滤。 否则,我只想要该合同号的信息(Else @ContractNo的原因)。
Recursive的帖子正好解决了我的问题。
我看到有关我原帖的清晰度的投诉。 在未来,我能做些什么才能让我说的更直接? 我不习惯于对代码的问题进行措辞,并为任何混乱的事情道歉。 我是否只需要在第二篇文章中提供扩展的详细信息?
再次感谢所有的帮助。
你的意思不是这样吗?
SELECT *
FROM tblContracts
WHERE
CASE
WHEN tblContracts.ContractNo = 0 THEN @ContractNo
ELSE tblContracts.ContractNo
END = tblContracts.ContractNo
其中@ContractNo是与tblContracts.ContractNo相同的数据类型的变量
为什么你甚至需要一个案例陈述?
当@ContractNo = 0然后(0 = tblContracts.ContractNo)否则@ContractNo然后(@ContractNo = tblContracts.ContractNo)
这没有任何意义,因为你可以简单地写这个
其中@contractNo = tblContracts.contractNo
合同号实际上是数字还是字符串总是恰好是数字。 检查表与参数和CASE语句之间的数据类型(例如,“= 0”或“='0'”)
这个语法应该有效(在Oracle中)
WHERE CASE WHEN tblContracts.ContractNo = 0
THEN @ContractNo
ELSE tblContracts.ContractNo
END = tblContracts.ContractNo
当你说:
我从一堆不同的表中提取,并使用select语句中未包含的信息过滤内容(即tblContracts没有通过Select从中提取信息,它仅在Where中使用)。 用户将从具有不同合同号的组合框中进行选择,以及默认值“全部”。
然后听起来应该有一个“Where exists”条款。 既然你没有从那张桌子中取出任何信息?!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.