Meilleur type de données pour stocker les valeurs monétaires dans une base de données MySQL

Réponses:

227

Quelque chose comme ça Decimal(19,4)fonctionne généralement bien dans la plupart des cas. Vous pouvez ajuster l'échelle et la précision pour répondre aux besoins des nombres que vous devez stocker. Même dans SQL Server, j'ai tendance à ne pas utiliser " money" car il n'est pas standard.

Kibbee
la source
52
Un point sur la taille: selon MSDN ( msdn.microsoft.com/en-us/library/ms187746.aspx ), Decimal (10,4) et Decimal (19,4) utilisent tous deux 9 octets de stockage, donc pourrait bien ressort pour que 9 chiffres supplémentaires d'échelle.
Adam Nofsinger
1
L'article MSDN concerne SQL Server mais la question concerne MySQL. (J'ai rencontré des développeurs qui pensent que les deux sont les mêmes, donc il
vaut
5
Quel est l'avantage d'utiliser à la (19,4)place de (19,2)?
ryvantage
1
Mon avantage était le suivant. J'avais besoin que toutes mes lignes de table correspondent à un montant d'argent particulier. Disons que ce montant est de 10,00 $. À mesure que de nouvelles lignes sont ajoutées, le montant de chaque ligne change. S'il y a 3 lignes dans le tableau. 10/3 = 3,3333333333 ... mais avec seulement 2 décimales, ils sont stockés sous la forme 3,33. Donc, lorsque vous les résumez, 3,33 + 3,33 + 3,33 = 9,99. Nous avons perdu un sou! Est encore pire sur un ensemble de données plus important. Stockez à 19,4 et additionnez vos totaux, puis arrondissez la sortie à 19,2 ..
Rick
49

La seule chose à laquelle vous devez faire attention est que si vous migrez d'une base de données à une autre, vous pouvez constater que DECIMAL (19,4) et DECIMAL (19,4) signifient des choses différentes

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

    DBASE: 10,5 (10 entier, 5 décimal)
    MYSQL: 15,5 (15 chiffres, 10 entiers (15-5), 5 décimaux)
SeanJA
la source
Le lien est maintenant mort, malheureusement.
Marco Aurélio Deleu
1
@ MarcoAurélioDeleu - J'ai changé le lien pour pointer vers la page sur la Wayback Machine, donc vous pouvez la voir comme regardée en arrière en 2009.
Tony
17

Il est également important de déterminer combien de décimales peuvent être nécessaires pour vos calculs.

J'ai travaillé sur une application de cours de bourse qui nécessitait le calcul du prix d'un million d'actions. Le prix de l'action coté devait être stocké à 7 chiffres de précision.

Horrible
la source
7
C'est un bon point - en particulier dans les applications financières, le "prix" n'implique certainement pas "l'argent"
Mike Woodhouse
17

Réponse d'Assaf de

Cela dépend de combien d'argent vous avez ...

semble désinvolte, mais en fait c'est pertinent.

Aujourd'hui seulement, nous avons eu un problème où un enregistrement n'a pas pu être inséré dans notre table de taux, car l'une des colonnes (GrossRate) est définie sur Decimal (11,4), et notre service produit vient d'obtenir un contrat pour des chambres dans un complexe incroyable à Bora Bora, qui se vendent plusieurs millions de francs pacifiques par nuit ... ce qui n'avait jamais été prévu lorsque le schéma de la base de données a été conçu il y a 10 ans.

Scott Ferguson
la source
2
C'est pourquoi j'ai recommandé la décimale (19,4). Cela peut sembler exagéré, mais vous ne savez jamais quand vous devrez stocker une très grande quantité dans ce domaine.
Kibbee
2
@Kibbee: Je ne serais pas d'accord avec vous sur nos exigences jusqu'à aujourd'hui. (Pendant 6 ans (11,4) était parfaitement bien ...)
Scott Ferguson
@Kibbee Cela ressemble à un mème de 640 Ko :)
Nikita Bosik
13

Pour les applications comptables, il est très courant de stocker les valeurs sous forme d'entiers (certains vont même jusqu'à dire que c'est le seul moyen). Pour vous faire une idée, prenez le montant des transactions (supposons 100,23 $) et multiple de 100, 1000, 10000, etc. pour obtenir la précision dont vous avez besoin. Donc, si vous avez seulement besoin de stocker des cents et que vous pouvez arrondir vers le haut ou vers le bas en toute sécurité, multipliez simplement par 100. Dans mon exemple, cela ferait 10023 comme entier à stocker. Vous économiserez de l'espace dans la base de données et comparer deux entiers est beaucoup plus facile que de comparer deux flottants. Mon 0,02 $.

Dane Bendixen
la source
Comment conservez-vous 6.125 (6 1/8)?
PeterToTheThird
Je suppose qu'il le stockerait comme un entier 6125.
Jimmy Knoot
2
Comment serait-ce mieux que ça DECIMAL? Vous devez faire très attention à toujours convertir des pièces de monnaie, des moulins ou des millrays en dollars, aux moments appropriés.
J'ai lu que les performances sont généralement plus rapides avec INT qu'avec DECIMAL, même dans les dernières versions de MySQL. C'est aussi plus facile lorsque vous devez importer ces valeurs dans PHP ou quelque chose et comparer les valeurs.
Dane Bendixen
9

entrée super tardive mais les PCGR sont une bonne règle de base ..

Si votre application doit gérer des valeurs monétaires pouvant atteindre un billion, cela devrait fonctionner: 13,2 Si vous devez vous conformer aux PCGR (principes comptables généralement reconnus), utilisez: 13,4

Habituellement, vous devez additionner vos valeurs monétaires à 13,4 avant d'arrondir la sortie à 13,2.

Source: meilleur type de données pour stocker la valeur monétaire dans MySQL

Damian
la source
5

Vous pouvez utiliser quelque chose comme DECIMAL(19,2)par défaut pour toutes vos valeurs monétaires, mais si vous ne stockez jamais que des valeurs inférieures à 1000 $, cela va juste être un gaspillage d'espace de base de données précieux.

Pour la plupart des implémentations, ce DECIMAL(N,2)serait suffisant, où la valeur de Nest au moins le nombre de chiffres avant .la plus grande somme que vous vous attendiez à être stockée dans ce champ + 5. Donc, si vous ne vous attendez jamais à stocker des valeurs supérieures à 999999,99, cela DECIMAL(11,2)devrait être plus que suffisant (jusqu'à ce que les attentes changent).

Si vous voulez être conforme aux PCGR , vous pouvez aller avec DECIMAL(N,4), où la valeur de Nest au moins le nombre de chiffres avant .la plus grande somme que vous vous attendez à être stockée dans ce champ + 7.

John Slegers
la source
3

Cela dépend de la nature des données. Vous devez le contempler au préalable.

Mon cas

  • décimal (13,4) non signé pour l'enregistrement des transactions monétaires
    • stockage efficace (4 octets de chaque côté de la virgule décimale de toute façon) 1
    • Conforme aux PCGR
  • décimal (19,4) non signé pour les agrégats
    • nous avons besoin de plus d'espace pour les totaux de plusieurs transactions de plusieurs milliards
    • la semi-conformité avec le type de données MS Currency ne fera pas de mal 2
    • cela prendra plus d'espace par enregistrement (11 octets - 7 à gauche et 4 à droite), mais c'est très bien car il y a moins d'enregistrements pour les agrégats 1
  • décimal (10,5) pour les taux de change
    • ils sont normalement cités avec 5 chiffres au total afin que vous puissiez trouver des valeurs comme 1.2345 & 12.345 mais pas 12345.67890
    • c'est une convention répandue, mais pas une norme codifiée (du moins à ma connaissance de recherche rapide)
    • vous pouvez le rendre décimal (18,9) avec le même stockage, mais les restrictions de type de données sont un mécanisme de validation intégré précieux

Pourquoi (M, 4)?

  • il y a des devises qui se divisent en mille sous
  • il y a des équivalents monétaires comme "Unidad de Fermento", "CLF" exprimés avec 4 décimales significatives 3 , 4
  • il est conforme aux PCGR

Troquer

  • précision inférieure:
    • moins de frais de stockage
    • calculs plus rapides
    • risque d'erreur de calcul plus faible
    • sauvegarde et restauration plus rapides
  • une plus grande précision:
    • compatibilité future (les chiffres ont tendance à augmenter)
    • gain de temps de développement (vous n'aurez pas à reconstruire la moitié d'un système lorsque les limites seront atteintes)
    • risque réduit d'échec de production en raison d'une précision de stockage insuffisante

Compatible Extreme

Bien que MySQL vous permette d'utiliser décimal (65,30), 31 pour l'échelle et 30 pour la précision semblent être nos limites si nous voulons laisser l'option de transfert ouverte.

Échelle et précision maximales dans les SGBDR les plus courants:

            Échelle de précision
Oracle 31 31
T-SQL 38 38
MySQL 65 30
PostgreSQL 131072 16383

6 , 7 , 8 , 9

Extrême raisonnable

  1. Pourquoi (27,4)?
    • on ne sait jamais quand le système doit stocker des dollars zimbabwéens

Septembre 2015 Le gouvernement zimbabwéen a annoncé qu'il échangerait des dollars zimbabwéens contre des dollars américains à un taux de 1 USD à 35 quadrillions de dollars zimbabwéens 5

Nous avons tendance à dire "oui, bien sûr ... je n'aurai pas besoin de ces chiffres fous". Eh bien, les Zimbabwéens disaient ça aussi. Il n'y a pas si longtemps.

Imaginons que vous ayez besoin d'enregistrer une transaction de 1 mln USD en dollars zimbabwéens (peut-être peu probable aujourd'hui, mais qui sait à quoi cela ressemblera dans 10 ans?).

  1. (1 mln USD) * (35 Quadrylion ZWL) = (10 ^ 6) * (35 * 10 ^ 15) = 35 * 10 ^ 21
  2. nous avons besoin:
    • 2 chiffres pour enregistrer "35"
    • 21 chiffres pour stocker les zéros
    • 4 chiffres à droite du séparateur décimal
  3. cela fait décimal (27,4) qui nous coûte 15 octets pour chaque entrée
  4. nous pouvons ajouter un chiffre à gauche sans frais - nous avons un nombre décimal (28,4) pour 15 octets
  5. Maintenant, nous pouvons stocker une transaction de 10 millions USD exprimée en dollars zimbabwéens, ou à l'abri d'une nouvelle grève d'hiperinflation, qui, espérons-le, ne se produira pas.
kshishkin
la source
0

Bien que cela puisse être en retard, mais cela sera utile à quelqu'un d'autre. D'après mon expérience et mes recherches, j'ai appris à connaître et à accepter les décimales (19, 6). C'est lorsque je travaille avec php et mysql. lorsque vous travaillez avec une grande quantité d'argent et un taux de change

précieux
la source