Лучший тип данных для хранения значений валюты в базе данных MySQL

Какой тип данных SQL является лучшим для значений валюты? Я использую MySQL, но предпочел бы независимый от базы данных тип.

10 ответов

Решение

Что-то вроде Decimal(19,4) обычно работает довольно хорошо в большинстве случаев. Вы можете настроить масштаб и точность в соответствии с потребностями чисел, которые вам нужно хранить. Даже в SQL Server я склонен не использоватьmoney"как это нестандартно.

Единственное, на что вам следует обратить внимание - если вы перейдете из одной базы данных в другую, вы можете обнаружить, что DECIMAL(19,4) и DECIMAL(19,4) означают разные вещи.

( http://dev.mysql.com/doc/refman/5.1/en/precision-math-decimal-changes.html)

    DBASE: 10,5 (10 целых, 5 десятичных)
    MYSQL: 15,5 (15 цифр, 10 целых (15-5), 5 десятичных)

Также важно определить, сколько десятичных знаков может потребоваться для ваших расчетов.

Я работал над заявкой на цену акций, которая требовала расчета цены одного миллиона акций. Указанная цена акции должна была храниться с точностью до 7 цифр.

Ответ Асафа о

Зависит от того, сколько денег вы получили...

звучит легкомысленно, но на самом деле это уместно.

Только сегодня у нас возникла проблема, из-за которой запись не удалось вставить в нашу таблицу тарифов, поскольку один из столбцов (GrossRate) установлен на десятичное число (11,4), а наш отдел продуктов только что получил контракт на номера в каком-то удивительном курорте в Бора-Бора, которые продают за несколько миллионов тихоокеанских франков за ночь... то, что никогда не придавало значения при разработке схемы базы данных 10 лет назад.

Для бухгалтерских приложений очень часто хранить значения в виде целых чисел (некоторые даже заходят так далеко, что говорят, что это единственный способ). Чтобы получить представление, возьмите сумму транзакций (предположим, $100,23) и умножьте ее на 100, 1000, 10000 и т. Д., Чтобы получить необходимую точность. Так что если вам нужно только хранить центы и можно безопасно округлять вверх или вниз, просто умножьте на 100. В моем примере это будет 10023 как целое число для хранения. Вы сэкономите место в базе данных, и сравнение двух целых чисел будет намного проще, чем сравнение двух чисел с плавающей запятой. Мои $0,02.

Это зависит от характера данных. Вы должны обдумать это заранее.

Мое дело

  • десятичная (13,4) без знака для записи денежных операций
    • эффективное хранение (4 байта для каждой стороны десятичной точки в любом случае) 1
    • GAAP-совместимый
  • десятичный (19,4) без знака для агрегатов
    • нам нужно больше места для итогов нескольких многомиллиардных транзакций
    • несоответствие типу данных MS Currency не повредит 2
    • для каждой записи потребуется больше места (11 байт - 7 слева и 4 справа), но это нормально, поскольку для агрегатов меньше записей 1
  • десятичный (10,5) для обменных курсов
    • они обычно заключаются в 5 цифр, поэтому вы можете найти такие значения, как 1.2345 и 12.345, но не 12345.67890
    • это широко распространенное соглашение, но не кодифицированный стандарт (по крайней мере, насколько мне известно)
    • вы можете сделать его десятичным (18,9) с тем же хранилищем, но ограничения типа данных являются ценным встроенным механизмом проверки

Почему (М,4)?

  • Есть валюты, которые разделены на тысячу копеек
  • есть денежные эквиваленты, такие как "Unidad de Fermento", "CLF", выраженные с 4 значащими десятичными знаками 3, 4
  • это соответствует GAAP

Компромисс

  • низкая точность:
    • меньшая стоимость хранения
    • более быстрые вычисления
    • меньший риск ошибки расчета
    • более быстрое резервное копирование и восстановление
  • высокая точность:
    • совместимость в будущем (цифры имеют тенденцию к росту)
    • экономия времени на разработку (вам не придется восстанавливать половину системы при соблюдении ограничений)
    • меньший риск отказа производства из-за недостаточной точности хранения

Совместимый Экстрим

Хотя MySQL позволяет использовать десятичную (65,30), 31 для масштаба и 30 для точности кажутся нашими ограничениями, если мы хотим оставить опцию передачи открытой.

Максимальный масштаб и точность в наиболее распространенных СУБД:

            Точность Шкала
Oracle 31 31
T-SQL 38 38
MySQL 65 30
PostgreSQL 131072 16383

6, 7, 8, 9

Разумный Экстрим

  1. Почему (27,4)?
    • Вы никогда не знаете, когда система должна хранить доллары Зимбабве

Сентябрь 2015 года Правительство Зимбабве заявило, что оно будет обменивать зимбабвийские доллары на доллары США по курсу от 1 до 35 квадриллионов зимбабвийских долларов 5

Мы склонны говорить: "Да, конечно... Мне не понадобятся эти сумасшедшие цифры". Ну, зимбабвийцы тоже так говорили. Не так давно

Давайте представим, что вам нужно записать транзакцию в 1 млн долларов в зимбабвийских долларах (возможно, вряд ли сегодня, но кто знает, как это будет выглядеть через 10 лет?).

  1. (1 млн. Долл. США) * (35 квадрилионов ZWL) = ( 10^6) * (35 * 10^15) = 35 * 10^21
  2. нам нужно:
    • 2 цифры до магазина "35"
    • 21 цифра для хранения нулей
    • 4 цифры справа от десятичной точки
  3. это делает десятичное число (27,4), что стоит нам 15 байтов для каждой записи
  4. мы можем добавить еще одну цифру слева без затрат - у нас есть десятичное число (28,4) для 15 байтов
  5. Теперь мы можем хранить транзакцию на сумму 10 млн. Долларов США, выраженную в зимбабвийских долларах, или обеспечить защиту от очередной вспышки гиперинфляции, которая, как мы надеемся, не произойдет

Супер поздняя запись, но GAAP - хорошее эмпирическое правило

Если ваше приложение должно обрабатывать денежные значения до триллиона, то это должно работать: 13,2 Если вам нужно соблюдать GAAP (общепринятые принципы бухгалтерского учета), тогда используйте: 13,4

Обычно вы должны суммировать свои денежные значения в 13,4 до округления результата до 13,2.

Источник: Лучший тип данных для хранения денежной стоимости в MySQL

Вы могли бы использовать что-то вроде DECIMAL(19,2) по умолчанию для всех ваших денежных значений, но если вы когда-либо будете хранить значения ниже 1000 долларов, это будет пустой тратой ценного пространства базы данных.

Для большинства реализаций DECIMAL(N,2) было бы достаточно, где значение N по крайней мере количество цифр перед . самой большой суммы, которую вы когда-либо ожидали хранить в этом поле + 5, Так что если вы никогда не ожидаете хранить какие-либо значения больше 999999,99, DECIMAL(11,2) должно быть более чем достаточно (пока не изменятся ожидания).

Если вы хотите соответствовать GAAP, вы можете пойти с DECIMAL(N,4)где значение N по крайней мере количество цифр перед . самой большой суммы, которую вы когда-либо ожидали хранить в этом поле + 7,

Хотя это может быть поздно, но это будет полезно для кого-то еще. Из моего опыта и исследований я узнал и принял десятичное число (19, 6). Это при работе с php и mysql. при работе с большой суммой денег и курсом обмена

Краткий ответ: я бы рекомендовал использовать десятичную дробь с точностью в соответствии с вашими потребностями. Десятичный с точностью = 0 может быть вариантом, если вы хотите хранить целое число второстепенных единиц валюты (например, центов) и у вас есть проблемы с обработкой десятичных знаков в вашем языке программирования.

Чтобы определить необходимую точность, необходимо учитывать следующее:

  • Типы валют, которые вы поддерживаете (они могут иметь разное количество знаков после запятой). Криптовалюты имеют до 18 знаков после запятой (ETH). Количество десятичных знаков может меняться со временем из-за инфляции.
  • Хранение цен на небольшие единицы товаров (вероятно, в результате конвертации из другой валюты) или наличие накопителей может потребовать использования большего количества десятичных знаков, чем определено для валюты.

Хранение целочисленного количества минимальных единиц может привести к необходимости масштабирования значений в будущем, если вам потребуется изменить точность. Если вы используете десятичные дроби, это намного проще.

Подробности и предостережения в статье .

Другие вопросы по тегам