Home > Mobile >  MS SQL Server Unexpected Behavior
MS SQL Server Unexpected Behavior

Time:09-17

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?

CodePudding user response:

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

CodePudding user response:

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
  • Related