💡 SQL-трюк: сравнивайте `NULL` без костылей
В PostgreSQL обычное сравнение может неожиданно сломать условие:
SELECT NULL = NULL;
Результат:
NULL
Потому что NULL означает «неизвестное значение», а не конкретное значение.
Из-за этого часто пишут громоздкие условия:
WHERE a = b
OR (a IS NULL AND b IS NULL)
Но есть оператор, о котором многие забывают:
a IS NOT DISTINCT FROM b
Он работает как NULL-safe equality:
SELECT NULL IS NOT DISTINCT FROM NULL; -- true
SELECT 10 IS NOT DISTINCT FROM 10; -- true
SELECT 10 IS NOT DISTINCT FROM NULL; -- false
Есть и обратный вариант:
a IS DISTINCT FROM b
Например, удобно искать реально изменившиеся значения:
SELECT *
FROM old_data o
JOIN new_data n USING (id)
WHERE o.email IS DISTINCT FROM n.email;
Если оба email = NULL, строка не считается изменённой.
Без этого обычное:
o.email n.email
может просто вернуть NULL и пропустить изменение.
Особенно полезно при синхронизации данных, аудите изменений, ETL и UPSERT-логике.
#SQL #PostgreSQL #Database
В PostgreSQL обычное сравнение может неожиданно сломать условие:
SELECT NULL = NULL;
Результат:
NULL
Потому что NULL означает «неизвестное значение», а не конкретное значение.
Из-за этого часто пишут громоздкие условия:
WHERE a = b
OR (a IS NULL AND b IS NULL)
Но есть оператор, о котором многие забывают:
a IS NOT DISTINCT FROM b
Он работает как NULL-safe equality:
SELECT NULL IS NOT DISTINCT FROM NULL; -- true
SELECT 10 IS NOT DISTINCT FROM 10; -- true
SELECT 10 IS NOT DISTINCT FROM NULL; -- false
Есть и обратный вариант:
a IS DISTINCT FROM b
Например, удобно искать реально изменившиеся значения:
SELECT *
FROM old_data o
JOIN new_data n USING (id)
WHERE o.email IS DISTINCT FROM n.email;
Если оба email = NULL, строка не считается изменённой.
Без этого обычное:
o.email n.email
может просто вернуть NULL и пропустить изменение.
Особенно полезно при синхронизации данных, аудите изменений, ETL и UPSERT-логике.
#SQL #PostgreSQL #Database