Короткий ответ
FLOAT/DOUBLE хранят числа с приблизительной точностью и могут давать мелкие ошибки округления при суммировании денежных значений, тогда как NUMERIC/DECIMAL (или целые копейки в INTEGER) хранят точное значение — поэтому для денег предпочтительны NUMERIC или целочисленное хранение в минимальных единицах.
Как это работает подробнее
FLOAT/DOUBLE PRECISION — это числа с плавающей точкой по стандарту IEEE 754, они не могут точно представить многие десятичные дроби (например, 0.1), из-за чего при множестве сложений может накопиться заметная погрешность. NUMERIC(p, s) хранит точное десятичное значение с заданной точностью, хоть и немного медленнее в вычислениях.
Пример кода
Запрос SQL
SELECT SUM(price) FROM order_items; -- price NUMERIC(10,2)Что использовать на практике
- На практике: для сумм в отчётах, особенно при проверке «сходится ли общая выручка до копейки» с бухгалтерией, разница между
FLOATиNUMERICможет стать заметной на больших объёмах операций. Хранение цены как целого числа копеек — ещё один надёжный способ избежать проблем с округлением вообще. - Результат: Если все 10000 позиций по 19.99, результат должен быть ровно 199900.00.
- Проверка: пересчитать вручную
COUNT(*) * 19.99и сравнить с результатомSUM.
Подводные камни
- Частая ошибка: сравнивают денежные
FLOAT-значения на точное равенство (price = 19.99) и получают неожиданныйFALSEиз-за погрешности представления; не замечают, чтоSUMпо множествуFLOAT-строк слегка «не бьётся» с ожидаемым контрольным числом.