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

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

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

5 ответов


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

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


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

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

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

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

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

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


ваш выбор:

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

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

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


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

numeric(15,6)

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

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


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

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

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

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

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