基于 SQL Server 参数值的条件 WHERE

Den*_*s R 4 sql sql-server sql-server-2008

我正在修改 SQL Server 中的现有存储过程,并尝试提出一个查询,该查询应该WHERE根据输入参数之一是null值还是具有值而采用条件。

存储过程接受三个输入参数

@FromDate
@ToDate
@PersonnelNo
Run Code Online (Sandbox Code Playgroud)

@FromDate并且@ToDate将始终具有价值并且将成为WHERE条件的一部分但@PersonnelNo可以为空或可以保持价值。

@PersonnelNo为空时,我希望所有用户都为给定的@FromDate@ToDate迄今为止的,但是当参数@PersonnelNo具有值时,我希望存储过程仅返回该用户的数据。

我已经尝试了以下两种方法,但它仅在我输入@PersonnelNo. 如果我输入@PersonnelNoas null,它不会返回任何记录,而是我想要所有用户。

知道我哪里出错了,或者我目前采取的方法有可能吗?

SELECT  FirstName,
        LastName,
        PersonnelNum,
        RecCreatedOn
FROM    [test].Person
WHERE   RecCreatedOn BETWEEN @FromDate AND @ToDate
        AND (
         (ISNULL(@PersonnelNo, 0) != 0 AND PersonnelNum = @PersonnelNo)
        )
Run Code Online (Sandbox Code Playgroud)

和稍微不同的 WHERE 子句

WHERE   RecCreatedOn BETWEEN @FromDate AND @ToDate
        AND ((@PersonnelNo IS NOT NULL) AND PersonnelNum = @PersonnelNo)
Run Code Online (Sandbox Code Playgroud)

Joh*_*van 6

这是通过说如果@PersonnelNo 为空则用PeronnelNum 替换它来工作的。PersonnelNum 将始终等于 PersonnelNum,因此如果 @PersonnelNo 为空,则此条件将始终为真。

SELECT  FirstName,
        LastName,
        PersonnelNum,
        RecCreatedOn
FROM    [test].Person
WHERE   RecCreatedOn BETWEEN @FromDate AND @ToDate
AND     (@PersonnelNo is null or PersonnelNum = @PersonnelNo)
Run Code Online (Sandbox Code Playgroud)

您之前尝试的解释:

ISNULL(@PersonnelNo, 0) != 0 AND PersonnelNum = @PersonnelNo
Run Code Online (Sandbox Code Playgroud)

如果@PersonnelNo 为空,则变为:

  • 0 != 0 and PersonnelNum = 0.
  • 这变成 false and false
  • 变成 false
  • 所以不会返回任何行

如果@PersonnelNo 是(例如)1,则变为:

  • 1 != 0 and PersonnelNum = 1.
  • 这变成 true and true (for the row where PersonnelNum is 1)
  • 变成 true
  • 所以你会看到第 1 个人所在的行。

    (@PersonnelNo 不为空) AND PersonnelNum = @PersonnelNo

如果@PersonnelNo 为空,则变为:

  • (null is not null) and PersonnelNum = null.
  • 这变成 false and false
  • 变成 false
  • 所以不会返回任何行

如果@PersonnelNo 是(例如)1,则变为:

  • 1 is not null and PersonnelNum = 1.
  • 这变成 true and true (for the row where PersonnelNum is 1)
  • 变成 true
  • 所以你会看到第 1 个人所在的行。

有效的方法:

  • PersonnelNum = coalesce(@PersonnelNo,PersonnelNum)
  • (@PersonnelNo is null or PersonnelNum = @PersonnelNo)

不过,上述方法之间存在细微差别。如果可以PersonnelNum为空,您可能会得到不同的结果;即该coalesce方法不会在此列中包含具有空值的行,而第二种方法会。

  • 这不会成为问题,因为(令人困惑地)null 不等于 null(而且它也不等于 null)。解释一下,如果你问某人他们的年龄,他们回答“我不知道”,你不能说他们和另一个说“我不知道”的人年龄相同,即使他们给出了相同的答案到问题。 (2认同)