NOT IN (SELECT ...) silently returns zero rows if the subquery result
contains any NULL. One of the most common SQL footguns. Use
NOT EXISTS or LEFT JOIN ... WHERE ... IS NULL instead.
Should fail
SELECT *
FROM customers
WHERE id NOT IN (SELECT customer_id FROM orders);
Should pass
SELECT *
FROM customers c
WHERE NOT EXISTS (
SELECT 1 FROM orders o WHERE o.customer_id = c.id
);
Implementation hints
- Multi-line rule.
- Regex:
r"\bNOT\s+IN\s*\(\s*SELECT\b".
- Severity:
warning (could argue error - open for discussion).
Estimated LOC: ~25 code + ~15 test.
NOT IN (SELECT ...)silently returns zero rows if the subquery resultcontains any
NULL. One of the most common SQL footguns. UseNOT EXISTSorLEFT JOIN ... WHERE ... IS NULLinstead.Should fail
Should pass
Implementation hints
r"\bNOT\s+IN\s*\(\s*SELECT\b".warning(could argueerror- open for discussion).Estimated LOC: ~25 code + ~15 test.