Задать вопрос

Как лучше хранить денежные суммы в Postgres?

Условно говоря, у меня есть товар, цена которого может быть указана в рублях, долларах и биткоинах. Для классических валют было бы удобно использовать рекомендуемый тип numeric/decimal с точностью 2 для копеек/центов. Но условный биткоин требует значительно большей точности (один сатоши = 0.00000001 btc). Таким образом, я стою перед выбором:
1) использовать для хранения денежных сумм numeric с точностью 8 (100,00000000 руб)
2) воспользоваться тем, что PG позволяет вообще не указывать точность для numeric (скорее всего не бесплатно)
3) хранить все денежные суммы в минимальных расчетных единицах, используя тип integer.

В случае с третьим вариантом, если товар, например, стоит 100 рублей, то в колонке с ценой будет указано значение 10000 (умножаем на 100 копеек). При этом в справочнике валют для рублей укажем кратность 100. А для биткоина уже 10 000 000.

Естественно, прежде чем выдавать данные на клиента, нужно будет задействовать функцию, которая преобразует значения в стандартный вид (делим на кратность).

Аналогично, если клиент отправит 0,00001 btc, то перед сохранением в базу нужно будет выполнить "конвертацию" в минимальные расчетные единицы (0,00001*10000000=1000).

Есть ли какие-то преимущества у третьего варианта перед первыми двумя (кроме того, что тип int работает значительно быстрее, чем numeric). Кто-нибудь использовал его в реальных проектах?
  • Вопрос задан
  • 2549 просмотров
Подписаться 8 Простой Комментировать
Ответ пользователя foterio К ответам на вопрос (4)
@foterio
Несколько лет назад, я потратил неделю чтобы гарантировано разобраться и принять правильное решение как хранить деньги в Postrgres.
3 вариант оказался единственно верным. Хранить деньги нужно в копейках, центах в виде int. Операции сложения вычитания так же необходимо проводить в копейках, центах. И только при выводе денег для конечного пользователя вы приводите его в читабельный вид $10.99
Ответ написан