NULL & three-valued logic
Concept  ·  SQL & Querying

amount + NULL and string concat with NULL both yield NULL — one NULL poisons the expression.

In expressions, NULL means 'unknown', and anything combined with unknown is unknown — one NULL field in a five-term formula nulls the result. But this is an operator rule, not a law of nature: functions define their own NULL behavior, and concat() treating NULL as empty-string is the one everyone meets first. Neither is wrong; not knowing which you're getting is.

See it break
batches
gradebarrel
A12
BNULL
The trap
SELECT
  grade,
  grade || '-' || barrelAS label
FROM
  batches
ORDER BY
  grade;
The fix
SELECT
  grade,
  concat(grade, '-', COALESCE(barrel, 'loose')) AS label
FROM
  batches
ORDER BY
  grade;
INPUTYour queryThe fix
AA-12A-12
BNULLB-loose

The batch label for the NULL barrel came out NULL — the || operator propagates NULL through the whole expression, while concat() skips NULLs and COALESCE supplies a stated default.

The rule

COALESCE per field with a meant default; know each function's policy (|| propagates, concat skips).

|| propagates NULL everywhere; concat() skips NULLs in DuckDB/Postgres/MySQL — check yours.

Shows up elsewhere
SUM over an empty / all-NULL groupCOALESCE / NULLIF mechanics
Try one →Prove it in practice →