Middle · Trace · SQL NULL and three-valued predicates

Portable .NET9 console only: predict every printed line and explain why the nullable comparison and the two counts differ. State which real HTTP, SQL or infrastructure guarantee this program does not test.

Think through your answer before opening the explanation.

Production engineering

using System;
using System.Linq;
using System.Collections.Generic;
using System.Globalization;
using System.Text;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;

bool? Equal(int? left,int? right) => left.HasValue&&right.HasValue ? left.Value==right.Value : null;
int?[] values={null,null,1,2,3}; Console.WriteLine(Equal(null,null)?.ToString()??"unknown"); Console.WriteLine("rows:"+values.Length); Console.WriteLine("known:"+values.Count(x=>x.HasValue));
Reveal answer and reasoning

The portable Equal helper deliberately returns nullable Boolean unknown whenever either operand lacks a value. Calling it with two nulls therefore prints unknown; this is not the behavior of every C# equality expression. The supplied nullable array has five slots and three populated integers, so the remaining lines are rows:5 and known:3. No SQL text is parsed, no connection is opened and no CHECK constraint executes.

The helper makes one proposed semantic boundary explicit over known inputs, while ordinary C# array and LINQ operations establish the exact counts printed by this companion.

The real /sql/nulls query reports equalsNull zero, isNull two, all five, known three and sum six. A separate POST begins an actual transaction, inserts NULL into the CHECK-only table, observes NOT NULL rejection in another table and rolls the whole experiment back. A fresh read still sees the original five rows. The checkAllowedNull observation therefore means one specific insert succeeded inside that transaction, not that an invalid candidate became durable data.

The independent post-rollback query is useful evidence that the fixture did not silently retain its temporary NULL row.

What a strong answer covers

  • WHERE retains true; NULL equality is unknown in the tested SQL contract.
  • The fixed fixture has5 rows,2 NULL amounts and3 known amounts with sum6.
  • CHECK-only NULL acceptance and NOT NULL rejection are independent actual SQLite checks.

Common pitfall

Assuming a positive-range CHECK also guarantees presence and a rigid integer type.

Follow-up questions

  1. What changes if every amount is NULL rather than zero?
  2. How would STRICT-table or type-affinity requirements be tested separately?

Self-review

Choose what to revisit. These marks are your own assessment and are separate from lesson completion.

Primary references

Open lesson and code ↗

← All interview questions