COALESCE and NULLIF
Master the two most important functions for handling NULL values in SQL.
- COALESCE β Returns the first non-NULL value from a list of expressions
- NULLIF β Returns NULL when two values are equal, preventing errors like division by zero NULL is not an error β it's a state. Handle it gracefully.
What Is COALESCE?
DfCOALESCE
COALESCE evaluates a list of expressions in order and returns the first non-NULL value. If all expressions are NULL, it returns NULL. Think of it as a fallback chain β SQL tries each value until it finds one that exists.
-- Basic COALESCE: returns first non-NULL value
SELECT
first_name,
COALESCE(nickname, first_name) AS display_name
FROM employees;
-- Multiple fallbacks: department, then team, then 'Unassigned'
SELECT
employee_name,
COALESCE(department, team, 'Unassigned') AS assignment
FROM staff;
-- Replacing NULL in aggregations
SELECT
department,
COALESCE(SUM(commission), 0) AS total_commission
FROM employees
GROUP BY department;
What Is NULLIF?
DfNULLIF
NULLIF compares two expressions and returns NULL if they are equal, otherwise it returns the first expression. It's primarily used to prevent errors like division by zero and to convert sentinel values (like 0 or empty strings) into proper NULLs.
-- Prevent division by zero
SELECT
order_id,
total_amount,
quantity,
total_amount / NULLIF(quantity, 0) AS unit_price
FROM order_items;
-- Convert a default value back to NULL
SELECT
employee_name,
NULLIF(bonus, 0) AS actual_bonus
FROM payroll;
-- Combined: COALESCE handles NULL, NULLIF handles zero
SELECT
employee_name,
COALESCE(NULLIF(salary, 0), 0) AS salary
FROM payroll
WHERE salary IS NOT NULL;
COALESCE vs CASE WHEN
DfCOALESCE is Syntactic Sugar
COALESCE(a, b, c) is functionally equivalent to a CASE expression that checks for NULL. It's shorter, cleaner, and more readable.
| Expression | Equivalent |
|---|---|
COALESCE(a, b, c) | CASE WHEN a IS NOT NULL THEN a WHEN b IS NOT NULL THEN b ELSE c END |
COALESCE(x, 0) | CASE WHEN x IS NOT NULL THEN x ELSE 0 END |
NULLIF(a, b) | CASE WHEN a = b THEN NULL ELSE a END |
Practical Examples
Employee Directory with Defaults
SELECT
employee_id,
first_name || ' ' || last_name AS full_name,
COALESCE(phone, 'No phone') AS phone,
COALESCE(email, 'No email') AS email,
COALESCE(extension, 'N/A') AS extension
FROM employees;
Salary Report with Commission Handling
SELECT
e.first_name || ' ' || e.last_name AS employee_name,
e.salary AS base_salary,
COALESCE(e.commission, 0) AS commission,
e.salary + COALESCE(e.commission, 0) AS total_compensation,
CASE
WHEN e.salary >= 100000 THEN 'Senior'
WHEN e.salary >= 60000 THEN 'Mid-Level'
ELSE 'Junior'
END AS level
FROM employees e;
Division Safety Pattern
-- Always use NULLIF when dividing to prevent runtime errors
SELECT
department_name,
total_budget,
employee_count,
total_budget / NULLIF(employee_count, 0) AS budget_per_employee
FROM department_stats;
Cleaning Import Data
-- Imported data may have 0 instead of NULL for missing values
SELECT
customer_id,
COALESCE(NULLIF(phone, ''), NULLIF(phone, '0'), 'Unknown') AS phone,
COALESCE(NULLIF(address, ''), 'No address') AS address
FROM imported_customers;
NULL Behavior Quick Reference
| Expression | Result | Explanation |
|---|---|---|
COALESCE(NULL, NULL, 5) | 5 | First non-NULL found at position 3 |
COALESCE(NULL, NULL, NULL) | NULL | All values are NULL |
COALESCE(1, 2, 3) | 1 | First value is already non-NULL |
NULLIF(5, 5) | NULL | Values are equal β returns NULL |
NULLIF(5, 3) | 5 | Values differ β returns first expression |
NULLIF(NULL, NULL) | NULL | Both NULL β returns NULL |
COALESCE(NULLIF(5, 5), 0) | 0 | NULLIF returns NULL, COALESCE falls back to 0 |
5 / NULLIF(0, 0) | NULL | Division by zero becomes NULL propagation |
Advanced Patterns
Conditional Aggregation with NULLIF
-- Calculate average salary only for departments with more than 3 employees
SELECT
department_id,
SUM(salary) / NULLIF(COUNT(*), 0) AS avg_salary
FROM employees
GROUP BY department_id
HAVING COUNT(*) > 3;
Pivoting with COALESCE
-- Pivot monthly sales into columns with NULL replacement
SELECT
product_id,
COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM sale_date) = 1 THEN amount END), 0) AS jan,
COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM sale_date) = 2 THEN amount END), 0) AS feb,
COALESCE(SUM(CASE WHEN EXTRACT(MONTH FROM sale_date) = 3 THEN amount END), 0) AS mar
FROM sales
GROUP BY product_id;
Null-Safe Comparisons
-- NULL-safe equality: COALESCE makes NULLs comparable
SELECT *
FROM employees
WHERE COALESCE(phone, '') = COALESCE(:input_phone, '');
Common Mistakes
| Mistake | Why It Fails | Fix |
|---|---|---|
COALESCE(NULL, NULL, NULL) | All values are NULL β returns NULL | Provide a default as the last argument |
NULLIF(0, 0) | Returns NULL β may cause unexpected results downstream | Wrap with COALESCE to supply a fallback |
salary / NULLIF(0, 0) | 0/0 is still 0, not NULL | Ensure the divisor is checked, not the dividend |
COALESCE(column, 'default') with mixed types | Type mismatch if column is INT and default is STRING | Use matching types in all positions |
Using = NULL instead of IS NULL | NULL is not equal to anything β comparison always returns NULL | Use IS NULL or IS NOT NULL for NULL checks |
| Nested NULLIF without COALESCE | Intermediate NULL may propagate unexpectedly | Wrap with COALESCE if you need a non-NULL result |
Performance Considerations
COALESCE and NULLIF are zero-cost at runtime. The database optimizer inlines them as simple comparisons. There is no performance penalty for using them liberally.
| Operation | Overhead |
|---|---|
COALESCE(a, b) | Equivalent to a single NULL check β negligible |
NULLIF(a, b) | Equivalent to a = b comparison β negligible |
CASE WHEN a IS NOT NULL THEN a ELSE b END | Same as COALESCE β no difference |
| Nested COALESCE chains (5+ values) | Still negligible β each is just a NULL check |
Portability Notes
| Feature | PostgreSQL | MySQL | SQL Server | Oracle | SQLite |
|---|---|---|---|---|---|
COALESCE | β | β | β | β | β |
NULLIF | β | β | β | β | β |
ISNULL() (SQL Server) | β | β | β | β | β |
IFNULL() (MySQL) | β | β | β | β | β |
NVL() (Oracle) | β | β | β | β | β |
Always prefer COALESCE over database-specific functions like ISNULL or NVL. COALESCE is ANSI SQL standard and works across all major databases.
When to Use Each
| Scenario | Use | Why |
|---|---|---|
| Replace NULL with a default value | COALESCE(col, default) | Clean, readable fallback |
| Prevent division by zero | NULLIF(divisor, 0) | Converts 0 to NULL, which propagates correctly |
| Convert sentinel values to NULL | NULLIF(col, sentinel) | Strips placeholder values |
| Multi-level fallback | COALESCE(a, b, c, d) | Chain alternatives in one expression |
| Conditional defaults with logic | CASE WHEN ... END | When you need complex branching beyond simple fallbacks |
Key Takeaways
- COALESCE returns the first non-NULL value β it's your universal NULL replacer
- NULLIF returns NULL when two values are equal β use it to prevent division by zero
- Both functions are ANSI SQL standard and portable across all major databases
- COALESCE is functionally equivalent to a CASE expression but far more readable
- There is no performance penalty β the optimizer inlines both as simple comparisons