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

Ответы:

227

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

Kibbee
источник
52
Вопрос о размере: в соответствии с MSDN ( msdn.microsoft.com/en-us/library/ms187746.aspx ), Decimal (10,4) и Decimal (19,4) оба используют 9 байт памяти, поэтому могут хорошо прыгнуть за эти дополнительные 9 цифр шкалы.
Адам Нофсингер
1
Статья MSDN о SQL Server, но вопрос о MySQL. (Я встречался с разработчиками, которые думают, что оба они одинаковы, поэтому лучше пояснить.)
cja
5
Какая польза от использования (19,4)вместо (19,2)?
ryvantage
1
Мое преимущество заключалось в следующем ... Мне нужно, чтобы все строки в моей таблице равнялись определенной сумме денег. Допустим, эта сумма составляет 10 долларов. По мере добавления новых строк количество каждой строки изменяется. Если в таблице 3 строки. 10/3 = 3.3333333333 ... но только с двумя десятичными знаками они сохраняются как 3.33. Таким образом, когда вы суммируете их, 3,33 + 3,33 + 3,33 = 9,99. Мы потеряли ни копейки! Становится еще хуже на большом наборе данных. Храните в 19,4 и суммируйте свои итоги, затем округлите результат до 19,2 ..
Рик
49

Единственное, на что вам следует обратить внимание - если вы переходите с одной базы данных на другую, вы можете обнаружить, что 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 десятичных)
SeanJA
источник
Ссылка сейчас мертва, к сожалению.
Марко Аурелио
1
@ MarcoAurélioDeleu - я изменил ссылку, чтобы указать на страницу на Wayback Machine, чтобы вы могли увидеть ее, как было в 2009 году.
Тони
17

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

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

Лия
источник
7
Это хороший момент - особенно в финансовых приложениях, «цена» наверняка не подразумевает «деньги»
Майк Вудхаус
17

Ответ Асафа о

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

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

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

Скотт Фергюсон
источник
2
Вот почему я рекомендовал десятичную (19,4). Может показаться излишним, но вы никогда не знаете, когда вам нужно будет хранить действительно большое количество в этой области.
Кибби
2
@Kibbee: я бы не согласился с вами на наши требования до сегодняшнего дня. (В течение 6 лет (11,4) было прекрасно ...)
Скотт Фергюсон
@Kibbee Это звучит как мем 640 Kb :)
Никита Босик
13

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

Датчанин Бендиксен
источник
Как вы храните 6,125 (6 1/8)?
PeterToTheThird
Я предполагаю, что он сохранил бы это как целое число 6125.
Джимми Кнот
2
Как это будет лучше, чем DECIMAL? Вы должны быть очень осторожны с тем, чтобы всегда переводить пенни, мельницы или миллионы в доллары в подходящее время.
Я читал, что производительность обычно выше с INT, чем DECIMAL, даже в последних версиях MySQL. Также проще, когда вам нужно перенести эти значения в PHP или что-то еще и сравнить значения.
датчанин Бендиксен
9

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

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

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

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

Damian
источник
5

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

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

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

Джон Слегерс
источник
3

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

Мое дело

  • десятичная (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 млн. Долларов США, выраженную в зимбабвийских долларах, или обеспечить защиту от очередной вспышки гиперинфляции, которая, как мы надеемся, не произойдет
kshishkin
источник
0

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

драгоценный
источник