在SQL Server 2005中处理比较测试中的空值

时间:2009-04-16 15:51:52

标签: sql sql-server tsql

我今天正在编写一个存储过程,遇到一个问题,如果其中一个值为null(无论是来自SELECT语句还是传入参数)我的表达式会评估如果它应该评估为真,那就是假。

SET ANSI_NULLS ON;
DECLARE @1 INT;
DECLARE @2 INT;
DECLARE @3 INT;
DECLARE @4 INT;

SET @1 = 1;
SET @2 = NULL;
SET @3 = 3;
SET @4 = 3;

IF ((@1 <> @2) OR (@3 <> @4))
   BEGIN
     SELECT 1;
   END
ELSE
   BEGIN
     SELECT 2;
   END
SELECT @1, @2, @3, @4

返回:

2

1, NULL, 3, 3

我期待它回归:

1

1, NULL, 3, 3

我知道我错过了一些简单的东西,任何人都知道它是什么?

相关问题

  

SQL: Why are NULL Values filtered Out within this WHERE clause?

5 个答案:

答案 0 :(得分:5)

解决此问题的一种方法是,您可以将NULL值包含在已知的意外值中,即-1

IF ((ISNULL(@1, -1) <> ISNULL(@2, -1)) OR (ISNULL(@3, -1) <> ISNULL(@4, -1)))
   BEGIN
     SELECT 1;
   END
ELSE
   BEGIN
     SELECT 2;
   END

显然,如果-1是可能的,那么使用不同的数字。如果没有不可能的值,那么您将不得不使用CASE语句。

NULL值分配给'安全'值的简明方法如下:

  

SET @1 = ISNULL(@1, -1)

这允许contional测试代码保持“无杂乱”。

答案 1 :(得分:4)

任何涉及NULL的比较都将计算为NULL而不是True或False。因此,代码的ELSE块被执行。因为尽管Null与False不同,但它肯定与True不同。

答案 2 :(得分:2)

是的,空是一种痛苦。处理它们的几种方法。其中一些是MS-SQL特定的功能:

方法1:明确所有选项

IF ((@1 <> @2) 
OR (@1 is NULL AND @1 IS NOT NULL)
OR (@1 is NOT NULL AND @1 IS NULL)
OR (@3 <> @4)
OR (@3 is NULL AND @4 IS NOT NULL)
OR (@3 is NOT NULL AND @4 IS NULL))

方法2:使用一个函数将null更改为其他您知道不匹配的函数:

IF ((IsNull(@1,-1) <> IsNull(@2,-1) 
OR (IsNull(@3,-1) <> IsNull(@4,-1))

有时这第一个选项更好,因为它更明确。 第二个具有将NULL与NULL匹配的副作用。

编辑:如果您想提前设置它们,请执行

SET @1 = IsNull(@1,-1);

如果为null,则将其设置为-1。如果没有,它将不管它。根据我的方法2,我认为它更清晰,可以在功能中进行。

答案 3 :(得分:2)

这是一种没有功能的方法,也可能更容易阅读。 (当我看到一堆NULL测试函数靠近时,我的眼睛开始交叉。)

IF (@1 IS NULL AND @2 IS NULL) OR (@1 = @2)
BEGIN
    IF (@3 IS NULL AND @4 IS NULL) OR (@3 = @4) 
    BEGIN
        SELECT 2
    END
    ELSE
    BEGIN
        SELECT 1
    END
END
ELSE
BEGIN
    SELECT 1
END

答案 4 :(得分:1)

如果您想更加困惑,请尝试运行相反的测试,如下所示:

SET ANSI_NULLS ON;
DECLARE @1 INT;
DECLARE @2 INT;
DECLARE @3 INT;
DECLARE @4 INT;
SET @1 = 1;
SET @2 = NULL;
SET @3 = 3;
SET @4 = 3;
IF ((@1 = @2) AND (@3 = @4))
   BEGIN     SELECT 1;
   ENDELSE   
   BEGIN     SELECT 2;   
   END
SELECT @1, @2, @3, @4

结果将不是您对之前实验的期望。

原因是SQL在评估时会参与复杂的三值逻辑 可能包含NULL的表达式。

NULL = 3不为TRUE。这也不算假。它是NULL。 NULL = NULL不为TRUE。这也不算假。它是NULL。

很容易让这一切搞砸了。避免混淆的最佳方法是将所有关键数据约束为NOT NULL。但是,这些要求可能会阻止你这样做,在这种情况下,你只需要弄清楚3种有价值的逻辑,即SQL风格。

不要让我为此辩护。

(在某些环境中,对于非TRUE或FALSE的结果,使用UNKNOWN代替NULL。)