Лучший тип данных для хранения значений валюты в базе данных 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) без знака для агрегатов
- десятичный (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
Разумный Экстрим
- Почему (27,4)?
- Вы никогда не знаете, когда система должна хранить доллары Зимбабве
Сентябрь 2015 года Правительство Зимбабве заявило, что оно будет обменивать зимбабвийские доллары на доллары США по курсу от 1 до 35 квадриллионов зимбабвийских долларов 5
Мы склонны говорить: "Да, конечно... Мне не понадобятся эти сумасшедшие цифры". Ну, зимбабвийцы тоже так говорили. Не так давно
Давайте представим, что вам нужно записать транзакцию в 1 млн долларов в зимбабвийских долларах (возможно, вряд ли сегодня, но кто знает, как это будет выглядеть через 10 лет?).
- (1 млн. Долл. США) * (35 квадрилионов ZWL) = ( 10^6) * (35 * 10^15) = 35 * 10^21
- нам нужно:
- 2 цифры до магазина "35"
- 21 цифра для хранения нулей
- 4 цифры справа от десятичной точки
- это делает десятичное число (27,4), что стоит нам 15 байтов для каждой записи
- мы можем добавить еще одну цифру слева без затрат - у нас есть десятичное число (28,4) для 15 байтов
- Теперь мы можем хранить транзакцию на сумму 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). Количество десятичных знаков может меняться со временем из-за инфляции.
- Хранение цен на небольшие единицы товаров (вероятно, в результате конвертации из другой валюты) или наличие накопителей может потребовать использования большего количества десятичных знаков, чем определено для валюты.
Хранение целочисленного количества минимальных единиц может привести к необходимости масштабирования значений в будущем, если вам потребуется изменить точность. Если вы используете десятичные дроби, это намного проще.
Подробности и предостережения в статье .