sql-not-in-nullable-trap
Installation
SKILL.md
The NOT IN / NULL trap
NOT IN over a subquery is the most common way to write a statement that can never be true.
It throws nothing, logs nothing, and matching zero rows is a perfectly ordinary outcome for a
DELETE, so the failure has no symptom at all except work that quietly does not happen.
Measured here: one playlist-cleanup statement deleted 0 rows and reported no error for as long as it existed, because the column it filtered against was nullable and mostly NULL.
The mechanism, exactly
x NOT IN (a, b, c) is defined as NOT (x = a OR x = b OR x = c). Comparing anything to NULL is
NULL, not false. So with a NULL anywhere in the list:
| case | inner OR | negated | matches? |
|---|---|---|---|
x is in the list |
TRUE OR NULL → TRUE |
FALSE |
no — correct |
x is not in the list |
FALSE OR NULL → NULL |
NULL |
no — wrong |