HiveBrain v1.2.0
Get Started
← Back to all entries
patternsqlMinor

Why is the result of a totally deterministic and all-encompassing "case" in select query in view nullable?

Submitted by: @import:stackexchange-dba··
0
Viewed 0 times
caseresultwhytheencompassingallquerytotallyviewnullable

Problem

I have a table, with Id as the primary key.

create table Anything
(
    Id bigint not null primary key identity(1, 1)
)


When I look at this table in Object Explorer, I see this image of course:

As you can see, column Id is not null.

Then I create a dummy view on this dummy table:

create view IdIsTwoView
as

select
    Id,
    (
        case
        when Id = 2
        then cast(1 as bit)
        else cast(0 as bit)
        end
    ) as IdIsTwo
from Anything


But this time, in Object Explorer I see this result:

As you can see, in spite of this fact that my case clause is all-encompassing and covers 100% of all records, and has an answer for all records, it's nullable.

Why does SQL Server have this weird behavior? And how do I force it to be not null?

P.S we have an infrastructure to generate code dynamically, and this behavior causes us trouble and we have to manually go and change all bool? types in C# to bool.

Solution

To answer the why part of your question, the CASE expression result is nullable because the CAST function result is nullable. This can be observed with:

EXEC sp_describe_first_result_set N'SELECT CAST(1 AS bit) AS result;';


Result (abbreviated):

+-----------+----------------+--------+-------------+----------------+------------------+
| is_hidden | column_ordinal |  name  | is_nullable | system_type_id | system_type_name |
+-----------+----------------+--------+-------------+----------------+------------------+
|         0 |              1 | result |           1 |            104 | bit              |
+-----------+----------------+--------+-------------+----------------+------------------+


The result is not null when a constant is specified without the function:

EXEC sp_describe_first_result_set N'SELECT 1 AS result;';

+-----------+----------------+--------+-------------+----------------+------------------+
| is_hidden | column_ordinal |  name  | is_nullable | system_type_id | system_type_name |
+-----------+----------------+--------+-------------+----------------+------------------+
|         0 |              1 | result |           0 |             56 | int              |
+-----------+----------------+--------+-------------+----------------+------------------+


But the result data type is int instead of the desired bit as SQL Server has no bit constant without implicit or explict conversion, ISNULL is needed to coerce a not null result as @MichaelGreen answered.

Code Snippets

EXEC sp_describe_first_result_set N'SELECT CAST(1 AS bit) AS result;';
+-----------+----------------+--------+-------------+----------------+------------------+
| is_hidden | column_ordinal |  name  | is_nullable | system_type_id | system_type_name |
+-----------+----------------+--------+-------------+----------------+------------------+
|         0 |              1 | result |           1 |            104 | bit              |
+-----------+----------------+--------+-------------+----------------+------------------+
EXEC sp_describe_first_result_set N'SELECT 1 AS result;';

+-----------+----------------+--------+-------------+----------------+------------------+
| is_hidden | column_ordinal |  name  | is_nullable | system_type_id | system_type_name |
+-----------+----------------+--------+-------------+----------------+------------------+
|         0 |              1 | result |           0 |             56 | int              |
+-----------+----------------+--------+-------------+----------------+------------------+

Context

StackExchange Database Administrators Q#262424, answer score: 8

Revisions (0)

No revisions yet.