0

I thought I understood SQL fairly well, but here is a simple example of NULL values introducing a bug that I didn't expect. Could someone explain why the first and second SELECT queries yield different results.

DROP TABLE IF EXISTS #temp;

CREATE TABLE #temp
(
    ITEM int,
    RELATIONSHIP nvarchar(max) NULL
)

INSERT INTO #temp VALUES (1, '')
INSERT INTO #temp VALUES (2, NULL)
INSERT INTO #temp VALUES (3, 'Parent')
INSERT INTO #temp VALUES (4, 'Child')


SELECT 
    ITEM, RELATIONSHIP, 
    CAST(CASE 
             WHEN (RELATIONSHIP != 'Parent' AND RELATIONSHIP != 'Child') 
                 THEN 0 
                 ELSE 1 
         END AS bit) family 
FROM 
     #temp;

SELECT 
    ITEM, RELATIONSHIP, 
    CAST(CASE 
             WHEN (RELATIONSHIP = 'Parent' OR RELATIONSHIP = 'Child') 
                 THEN 1 
                 ELSE 0 
         END AS bit) family 
FROM 
    #temp;

SELECT 
    ITEM, RELATIONSHIP, 
    CAST(CASE 
             WHEN (RELATIONSHIP IS NULL OR (RELATIONSHIP != 'Parent' AND RELATIONSHIP != 'Child')) 
                 THEN 0 
                 ELSE 1 
         END AS bit) family 
FROM 
    #temp;
ITEM    RELATIONSHIP    family
1                       0
2       NULL            1
3       Parent          1
4       Child           1

ITEM    RELATIONSHIP    family
1                       0
2       NULL            0
3       Parent          1
4       Child           1

ITEM    RELATIONSHIP    family
1                       0
2       NULL            0
3       Parent          1
4       Child           1

Is this because all scalar comparison of NULL values are always false and (false AND false) is always false?

MRodriguez
  • 379
  • 3
  • 10

2 Answers2

0

If I am correct, the result is different only for the second row. For the first query, the condition WHEN (RELATIONSHIP != 'Parent' AND RELATIONSHIP != 'Child') is false for NULL and for the second query, the condition WHEN (RELATIONSHIP = 'Parent' OR RELATIONSHIP = 'Child') is also false for NULL.

You have to handle NULL explicitly in sql server using IS NULL operator. I assume you have the confusion in your first query result. So in your first query, the condition should be

WHEN (RELATIONSHIP != 'Parent' AND RELATIONSHIP != 'Child') OR RELATIONSHIP IS NULL

SQL here

Md. Suman Kabir
  • 5,243
  • 5
  • 25
  • 43
  • I had included the "IS NULL" check version in the third select above. It's just caught me off guard because we usually think of checking for null values on the RHS of an expression and not the left. Also, it is a bit counter-intuitive from a human perspective (not programming or mathematical) that unknown != known is false and unknown = known is false. – MRodriguez Sep 16 '22 at 17:59
0

Comparison with NULL with any value (including NULL) results in UNKONWN which in binary logic will be translated to false.

Therefore x = NULL is UNKONWN (false) and x != NULL is UNKONWN (false) too. (Similarly x < NULL, x <= NULL, x > NULL, x >= NULL, etc will also result in UNKONWN).

NULL = NULL is also UNKONWN (false).

The only exception is testing against NULL via IS NULL.

ITEM    RELATIONSHIP    family    RELATIONSHIP = 'Parent'   RELATIONSHIP != 'Parent'
1                       0         false                     true
2       NULL            1         UNKONWN (false)           UNKONWN (false)
3       Parent          1         true                      false
4       Child           1         false                     true
Pred
  • 8,789
  • 3
  • 26
  • 46