PostgreSQL: какой тип данных следует использовать для валюты?


Кажется Money тип не рекомендуется, как описано здесь

мое приложение должно хранить валюту, какой тип данных я должен использовать? Числовые, деньги или поплавок?

5 84

5 ответов:

Numeric с принудительной точностью 2 единиц. Никогда не используйте float или float как тип данных для представления валюты, потому что если вы это сделаете, люди будут недовольны, когда итоговая цифра финансового отчета неверна на + или - несколько долларов.

тип денег просто остался по историческим причинам, насколько я могу судить.

ваш источник никоим образом не является официальным. Он датируется 2011 годом, и я даже не узнаю авторов. Если бы тип денег был "обескуражен" PostgreSQL сказал бы так в руководстве -чего он не делает.

на более официальный источник, читать этот поток в pgsql-general (только с этой недели!), с заявлениями от основных разработчиков, включая D'Arcy J. M. Cain (оригинальный автор типа money) и Tom Lane:

в основном, money имеет свои (ограниченные) применения. Преимущество над numeric и производительность.

decimal - это просто псевдоним для numeric в Postgres.

связанный ответ (и комментарии!) об улучшениях в последних релизах:

лично мне нравится хранить валюту как integer представляя центы. Это более эффективно, чем любой другой из упомянутых вариантов.

ваш выбор:

  1. integer: хранить сумму в центах. Это то, что используют транзакции EFTPOS.
  2. decimal(12,2): хранить сумму ровно с двумя десятичными знаками. Это то, что использует большинство программ главной книги.
  3. float : ужасная идея - недостаточная точность. Это то, что используют наивные разработчики.

Вариант 2 является наиболее распространенным и простым в работе. Сделать точность (12 в моем примере, что означает 12 цифр во всех) как большой или маленький, как лучше всего работает для вас.

обратите внимание, что если вы агрегируете несколько транзакций, которые были результатом расчета (например, с использованием обменного курса) в одно значение, которое имеет бизнес-значение, точность должна быть выше, чтобы обеспечить точное значение макроса; рассмотрите возможность использования чего-то вроде decimal(18, 8) Так сумма точна и индивидуальные значения можно округлить к точности цента для дисплея.

Я сохраняю все мои денежные поля как:

numeric(15,6)

кажется чрезмерным иметь так много десятичных знаков, но если есть даже малейший шанс, что вам придется иметь дело с несколькими валютами, вам понадобится такая точность для преобразования. Независимо от того, что я представляю пользователю, я всегда храню в долларах США. Таким образом, я могу легко конвертировать в любую другую валюту, учитывая курс конвертации за день.

Если вы никогда не делаете ничего, кроме одна валюта, самое худшее здесь то, что вы потратили немного места для хранения некоторых нулей.

после большого опыта работы во многих приложениях, что я рекомендую bigint, которое представляет собой 64-разрядное целое число, хранящее значения в микро-долларах (или аналогичной основной валюте).

микро = 1 миллионная, поэтому 1 Микро-доллар - это $ 1 / 1,000,000. Это обеспечивает очень тонкую гранулярность, которая может обрабатывать практически любую долю цента.

  • 64 бит целые числа малы, просты в хранении, просты в обращении, совместимы со всем, и избежать потери данных в проведенные расчеты.

  • особенно хорошо работает для небольших цен на единицу, таких как показы рекламных кампаний или сборы API.

  • легко поддерживать точность во всех расчетах и (как рекомендуется) применять округление на конечном выходе (например, создание счета-фактуры).