SQL:WHERE子句中的IF子句

Bry*_*oth 191 sql t-sql sql-server

是否可以在MS SQL中的WHERE子句中使用IF子句?

例:

WHERE
    IF IsNumeric(@OrderNumber) = 1
        OrderNumber = @OrderNumber
    ELSE
        OrderNumber LIKE '%' + @OrderNumber + '%'
Run Code Online (Sandbox Code Playgroud)

bdu*_*kes 204

使用CASE语句
更新:以前的语法(由少数人指出)不起作用.您可以按如下方式使用CASE:

WHERE OrderNumber LIKE
  CASE WHEN IsNumeric(@OrderNumber) = 1 THEN 
    @OrderNumber 
  ELSE
    '%' + @OrderNumber
  END
Run Code Online (Sandbox Code Playgroud)

或者您可以使用像@ NJ Reed指出的IF语句.

  • 我们如何将其与 IN 运算符一起使用? (4认同)

njr*_*101 131

您应该能够在没有任何IF或CASE的情况下执行此操作

 WHERE 
   (IsNumeric(@OrderNumber) AND
      (CAST OrderNumber AS VARCHAR) = (CAST @OrderNumber AS VARCHAR)
 OR
   (NOT IsNumeric(@OrderNumber) AND
       OrderNumber LIKE ('%' + @OrderNumber))
Run Code Online (Sandbox Code Playgroud)

根据SQL的风格,您可能需要将订单号上的强制转换调整为INT或VARCHAR,具体取决于是否支持隐式强制转换.

这是WHERE子句中非常常见的技术.如果要在WHERE子句中应用一些"IF"逻辑,您需要做的就是将带有布尔AND的额外条件添加到需要应用它的部分.

  • 我总是忘记在 SQL 中可以用这样的布尔逻辑替换条件语句。感谢您的提醒,这是一个非常有用的技术! (3认同)
  • 由于 SQL Server 处理布尔逻辑的方式,该解决方案实际上是最好的解决方案。where 子句中的 CASE 语句的效率低于布尔情况,因为如果第一次检查失败,SQL 将停止处理该行并继续。这可以节省您的处理时间。另外,始终将成本更高的语句放在布尔检查的另一侧。 (3认同)
  • 我想你会比CASE解决方案受到一点性能影响,因为所有这些条件都得到了评估,不是吗? (2认同)
  • 感谢您提供一个非常优雅的解决方案。找到了有关您使用的方法的教程,这可能会对人们有所帮助。http://weblogs.sqlteam.com/jeffs/archive/2003/11/14/513.aspx (2认同)

Riv*_*nni 23

您根本不需要IF语句.

WHERE
    (IsNumeric(@OrderNumber) = 1 AND OrderNumber = @OrderNumber)
OR (IsNumeric(@OrderNumber) = 0 AND OrderNumber LIKE '%' + @OrderNumber + '%')
Run Code Online (Sandbox Code Playgroud)

  • 我真的很喜欢这种方法。替代用途:仅在 AdmUseId 具有值时过滤:`where (@AdmUserId is null or CurrentOrder.CustomerAdmUserId = @AdmUserId)` 或仅在 IncludeDeleted = 0 时过滤:`where (@IncludeDeleted = 1 or ItemObject.DeletedFlag = 0)` (2认同)

Eur*_*lli 13

在SQL中没有一种好方法可以做到这一点.我看到的一些方法:

1)使用CASE结合布尔运算符:

WHERE
    OrderNumber = CASE 
        WHEN (IsNumeric(@OrderNumber) = 1)
        THEN CONVERT(INT, @OrderNumber)
        ELSE -9999 -- Some numeric value that just cannot exist in the column
    END
    OR 
    FirstName LIKE CASE
        WHEN (IsNumeric(@OrderNumber) = 0)
        THEN '%' + @OrderNumber
        ELSE ''
    END
Run Code Online (Sandbox Code Playgroud)

2)在SELECT之外使用IF

IF (IsNumeric(@OrderNumber)) = 1
BEGIN
    SELECT * FROM Table
    WHERE @OrderNumber = OrderNumber
END ELSE BEGIN
    SELECT * FROM Table
    WHERE OrderNumber LIKE '%' + @OrderNumber
END
Run Code Online (Sandbox Code Playgroud)

3)使用长字符串,有条件地编写SQL语句,然后使用EXEC

第三种方法很可怕,但如果您有许多可变条件,这几乎是唯一可行的方法.


小智 7

澄清一些逻辑等价解决方案。

if 语句

if (a) then b
Run Code Online (Sandbox Code Playgroud)

逻辑上等价于

(!a || b)
Run Code Online (Sandbox Code Playgroud)

这是逻辑等价维基百科文章中涉及条件语句的逻辑等价部分的第一行。

要包含else,您所要做的就是添加另一个条件

if(a) then b; 
if(!a) then c;
Run Code Online (Sandbox Code Playgroud)

逻辑上等价于 (!a || b) && (a || c)

所以以OP为例:

IF IsNumeric(@OrderNumber) = 1
    OrderNumber = @OrderNumber
ELSE
    OrderNumber LIKE '%' + @OrderNumber + '%'
Run Code Online (Sandbox Code Playgroud)

逻辑上的等价物是:

(IsNumeric(@OrderNumber) <> 1 OR OrderNumber = @OrderNumber)
AND (IsNumeric(@OrderNumber) = 1 OR OrderNumber LIKE '%' + @OrderNumber + '%' )
Run Code Online (Sandbox Code Playgroud)


Joe*_*orn 6

使用CASE语句而不是IF.