7

我在这里阅读了有关在 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 上使用通配符过滤。我现在专注于降低语法。我相信这应该返回参数与存储在表中的合同编号匹配的所有记录。任何帮助或建议将不胜感激。

4

12 回答 12

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 语句之外更好地工作。

于 2009-01-05T20:47:18.630 回答
7

阅读您的解释后,有一种更好的方法可以做到这一点CASE

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

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

编辑:我刚刚注意到casperOne 提出了同样的事情。我没看到。自己做大。

于 2009-01-05T21:15:27.713 回答
2

无论如何,请尝试忽略位于错误位置的括号 - 正确的括号应该在“END”之后。

于 2009-01-05T20:44:22.003 回答
2

也许你忘了声明@ContractNo?它可以与 0 和 tblContracts.ContractNo 相媲美吗?

于 2009-01-05T20:48:18.907 回答
1

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

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

我看不到这个case语句会做什么......如果@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)未在您的查询/程序范围内声明。但是有人已经指出了这一点,所以我不能对此表示赞赏。

于 2009-01-05T20:44:58.587 回答
1

case语句的原因,包括整个“如果为0,则给出参数,否则,只给出参数”是为了测试它以尝试使语法正确。最初,我曾尝试说“如果它是 0,则传入 '%',以返回每个值。我在那里发布的代码是因为我不断收到 'Invalid Parameter' 并认为我的语法一定有问题。当我把它分成基本参数匹配,像这样,

WHERE @ContractNo = tblContracts.ContractNo

它返回记录很好。让我再解释一下。

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

当组合框的索引更改时,我将举办一个活动。如果是“全部”,0 将作为参数传入,我不希望进行过滤。否则,我只想要该合同号的信息(Else @ContractNo 的原因)。

于 2009-01-05T21:05:58.700 回答
1

Recursive 的帖子准确地解决了我的问题。

我看到有人抱怨我的原始帖子的清晰度。将来,我可以做些什么来使我所说的更直接?我不习惯用措辞表达有关代码的问题,并为它所拥有的任何混乱的事情道歉。我是否只需要像我的第二篇文章那样提供详细信息?

再次感谢所有帮助。

于 2009-01-05T21:22:28.120 回答
0

你说的不是这样的吗?

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

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

于 2009-01-05T20:46:17.990 回答
0

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

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

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

其中@contractNo = tblContracts.contractNo

于 2009-01-05T20:47:28.050 回答
0

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

于 2009-01-05T21:00:51.987 回答
0

这种语法应该有效(它在 Oracle 中有效)

WHERE CASE WHEN tblContracts.ContractNo = 0 
           THEN @ContractNo 
           ELSE tblContracts.ContractNo
      END = tblContracts.ContractNo
于 2009-01-05T21:23:24.327 回答
0

当你说:

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

然后在我看来应该有一个“在哪里存在”子句。因为你没有从那张桌子上拉出任何信息?!

于 2009-01-05T21:38:26.840 回答