При добавлении CHECK-ограничения для проверки условий price > 0, discount >= 0 и price > discount в таблице с nullable полем discount возникла проблема. Какие потенциальные уязвимости появляются в такой реализации?
Подробное объяснение
Основная проблема заключается в том, что поле discount объявлено как NULLABLE (discount NUMERIC), а в CHECK-ограничении используются сравнения discount >= 0 и price > discount. В SQL сравнения с NULL всегда возвращают UNKNOWN, а не FALSE. Поскольку CHECK-ограничения пропускают строки, где условие равно TRUE или UNKNOWN, записи с discount = NULL будут успешно вставлены, хотя исходная бизнес-логика требовала discount > 0. Это создаёт уязвимость, позволяя обойти проверку корректности данных через установку NULL в поле скидки.
Часто задаваемые вопросы (FAQ)
1
Как SQL обрабатывает NULL в условиях CHECK?
В SQL CHECK-ограничение разрешает вставку строки, если условие возвращает TRUE или UNKNOWN. Сравнения с NULL (например, NULL > 0) всегда дают UNKNOWN, поэтому такие строки проходят проверку.
2
Как правильно реализовать проверку discount > 0 с учётом NULL?
Нужно либо сделать поле discount NOT NULL, либо явно добавить проверку на NULL в условие: (discount IS NULL OR (discount > 0 AND price > discount)).
3
Почему исходная бизнес-логика требовала discount > 0, а в CHECK используется discount >= 0?
В CHECK-ограничении допущена ошибка: вместо строгого неравенства discount > 0 используется нестрогое discount >= 0, что дополнительно ослабляет проверку и позволяет нулевые скидки.
Типичные ошибки
1
Использование сравнений с NULL без явной обработки
При сравнении NULL с любым значением результат всегда UNKNOWN, что может неявно разрешать некорректные данные. Нужно явно проверять IS NULL или использовать COALESCE.
2
Несоответствие CHECK-ограничения бизнес-требованиям
В ограничении используется discount >= 0 вместо требуемого discount > 0, что позволяет нулевые скидки, хотя логика требовала положительных значений.
3
Неучёт NULL при проектировании таблиц
Если поле должно всегда содержать значение для корректной работы логики, его нужно объявлять как NOT NULL. Разрешение NULL без соответствующей обработки в ограничениях создаёт уязвимости.