如果还测试大于?是否有必要测试NULL?

时间:2016-09-26 15:50:49

标签: sql-server tsql

我今天继承了一些旧的存储过程,并且遇到了一些遵循这种一般模式的示例,其中@Test有一些INT值:

IF @Test IS NOT NULL AND @Test > 0
    -- do something...

我的理解是,如果@TestNULL,那么它没有值,并且不大于,小于或甚至等于零。因此,在上面的代码中对NULL的测试是多余的:

IF @Test > 0
    -- do something...

第二个版本似乎工作正常,IHMO更具可读性。

所以,我的问题是:在这个例子中我对NULL的理解是否正确,或者是否有一些明显的用例我在这里忽略了它可能会出现可怕的错误?

注意:在某些情况下,显然意图检查是否存在值,我已将其更改为IF EXISTS ...我的问题更多关注上述一般情况。

4 个答案:

答案 0 :(得分:5)

在SQL中,所有与NULL值的比较都计算为false。 因此,如果您希望对其执行操作,则必须明确检查NULL。 因此,在这种情况下,不需要额外的测试。

答案 1 :(得分:4)

@FlorianHeer是对的。 NULL> 0将最终评估为false,但正如@Pred所指出的那样,因为Null> 0实际上计算为null并且null转换为某个位是错误的....

null是未知的,因此与它的任何比较也是未知的。考虑算术函数,例如加法1 + NULL = NULL或串联'A' + NULLL = NULL。 NULL表示SQL数据库引擎无法解释其值是什么,因此任何函数或其上的比较也是未知的。

@MikkaRin指出,它是案例陈述或IF语句的ELSE部分中的假设,其中可能会出现问题,但我们也要考虑在连接的上下文中以及您可能或不想看到的方式结果。

DECLARE @Table1 AS TABLE (Col INT)
DECLARE @Table2 AS TABLE (Col INT)
INSERT INTO @Table1 VALUES (1),(2),(3)
INSERT INTO @Table2 VALUES (1),(NULL),(3),(4)

SELECT *
FROM
    @Table1 t1
    INNER JOIN @Table2 t2
    ON t1.Col <> t2.Col

当然,您可能会认为因为NULL不等于1,2,3它应该包含在结果集中。但是null是未知的,所以SQL很好说我不知道​​NULL是否可以是1,2,3所以我不能返回那个结果。

现在让我们做同样的事情,但在第一个表中添加一个NULL:

DECLARE @Table1 AS TABLE (Col INT)
DECLARE @Table2 AS TABLE (Col INT)
INSERT INTO @Table1 VALUES (1),(2),(3),(NULL)
INSERT INTO @Table2 VALUES (1),(NULL),(3),(4)

SELECT *
FROM
    @Table1 t1
    INNER JOIN @Table2 t2
    ON t1.Col = t2.Col

你可能会认为NULL = = NULL但是任何NULL的比较都被认为是未知的,所以即使两个表都有NULL,它也不会在数据集中返回。

现在考虑:

DECLARE @Table1 AS TABLE (Col INT)
INSERT INTO @Table1 VALUES (1),(2),(3),(NULL)

SELECT *, CASE WHEN Col < 2 THEN Col ELSE 1000 END as ColCase
FROM
    @Table1 t1

哪个会使NULL 1000问题是NULL应该是一个未知的1000?如果NULL未知,我们怎么知道它不小于2?

对于很多操作来说,比较@Value > 1可能就足够了,但尤其是在IF语句开始处理ELSE或加入对等时,你应该考虑处理NULL。比如@GuidoG指出使用ISNULL()COALESCE()

恕我直言,明确表示您在操作过程中的意图,以便适当地考虑空值,从而减轻打字的最小节省。

答案 2 :(得分:2)

如果使用ELSE语句,则需要与NULL进行比较:

例如:

rowStyle

答案 3 :(得分:1)

你可以用

替换它
d

这样会更短,你仍然检查了一切