Je suis curieux de savoir s'il existe ou non une réelle différence entre le money
type de données et quelque chose comme decimal(19,4)
(c'est ce que l'argent utilise en interne, je crois).
Je suis conscient que money
c'est spécifique à SQL Server. Je veux savoir s'il y a une raison impérieuse de choisir l'un plutôt que l'autre; la plupart des exemples SQL Server (par exemple la base de données AdventureWorks) utilisent money
et non decimal
pour des choses comme les informations de prix.
Dois-je simplement continuer à utiliser le type de données money, ou y a-t-il un avantage à utiliser la décimale à la place? L'argent est moins de caractères à taper, mais ce n'est pas une raison valable :)
sql-server
types
Wayne Molina
la source
la source
DECIMAL(19, 4)
est un choix populaire vérifier ce aussi vérifier ici du monde Monnaie Formats de décider combien de décimales à l' utilisation, l' espoir aide.Réponses:
Vous ne devez jamais utiliser d'argent. Ce n'est pas précis et ce sont des ordures pures; utilisez toujours décimal / numérique.
Exécutez ceci pour voir ce que je veux dire:
Sortie: 2949.0000 2949.8525
À certaines des personnes qui ont dit que vous ne divisez pas l'argent par l'argent:
Voici l'une de mes requêtes pour calculer les corrélations, et changer cela en argent donne de mauvais résultats.
la source
money
plus demoney
côté, cette «illustration» est manipulatrice. C'est un fait documenté quimoney
a une précision fixe et très limitée. Dans de tels cas, il faut d'abord multiplier, puis diviser. Modifiez l'ordre des opérateurs dans cet exemple et vous obtiendrez des résultats identiques. Amoney
est essentiellement un entier 64 bits, et si vous deviez gérer des nombres entiers, vous vous multiplieriez avant de diviser.SQLMenace a déclaré que l'argent était inexact. Mais vous ne multipliez / divisez pas l'argent par l'argent! Combien coûte 3 dollars multiplié par 50 cents? 150 dollarcents? Vous multipliez / divisez l'argent par des scalaires, qui doivent être décimaux.
Résultats dans le bon résultat:
money
est bon tant que vous n'avez pas besoin de plus de 4 chiffres décimaux et que vous vous assurez que vos scalaires - qui ne représentent pas de l'argent - sontdecimal
s.la source
money / money
? La réponse est des unités entières sans signe dollar attaché, ce qui est correct! C'est un scénario parfaitement raisonnable, suggérant qu'en raison de cas de bord étranges comme celui-ci, cemoney
n'est pas un bon type de données à utiliser, car le résultat est toujours tronqué pour s'adaptermoney
au lieu de suivre les règles normales de précision et d'échelle. Que faire si vous souhaitez calculer l'écart type d'un ensemble demoney
valeurs? Oui,Sqrt(Sum(money * money))
(simplifié) a du sens.Tout est dangereux si vous ne savez pas ce que vous faites
Même les types décimaux de haute précision ne peuvent pas sauver la situation:
1,000000 <- Devrait être 0,6000000
Les
money
types sont des entiersLes représentations textuelles de
smallmoney
etdecimal(10,4)
peuvent se ressembler, mais cela ne les rend pas interchangeables. Vous grincer des dents quand vous voyez les dates stockées sousvarchar(10)
? C'est la même chose.Dans les coulisses,
money
/ nesmallmoney
sont qu'unbigint
/int
La virgule décimale dans la représentation textuellemoney
est un fluff visuel, tout comme les tirets d'une date aaaa-mm-jj. SQL ne les stocke pas réellement en interne.En ce qui concerne
decimal
vsmoney
, choisissez ce qui convient à vos besoins. Lesmoney
types existent car le stockage des valeurs comptables sous forme de multiples entiers de 1/10000ème d'unité est très courant. De plus, si vous traitez de l'argent réel et des calculs au-delà de la simple addition et soustraction, vous ne devriez pas le faire au niveau de la base de données! Faites-le au niveau de l'application avec une bibliothèque qui prend en charge l'arrondi bancaire (IEEE 754)la source
Je me rends compte que WayneM a déclaré qu'il savait que l'argent est spécifique à SQL Server. Cependant, il demande s'il y a des raisons d'utiliser de l'argent au-dessus de la décimale ou vice versa et je pense qu'une raison évidente doit encore être indiquée et que l'utilisation de la décimale signifie que c'est une chose de moins à s'inquiéter si vous devez changer votre SGBD - ce qui peut arriver.
Rendez vos systèmes aussi flexibles que possible!
la source
date
type, je dirais que vous aurez toujours de tels problèmes. Vous devez dire "N'utilisez pas de types obsolètes lorsque la base de données fournit déjà de meilleurs types, plus conformes aux normes et met en garde contre ceux qui sont obsolètes".Eh bien, j'aime bien
MONEY
! C'est un octet moins cher queDECIMAL
, et les calculs sont plus rapides car (sous les couvertures) les opérations d'addition et de soustraction sont essentiellement des opérations entières. L'exemple de @ SQLMenace - qui est un grand avertissement pour les ignorants - pourrait également être appliqué auxINT
egers, où le résultat serait nul. Mais ce n'est pas une raison pour ne pas utiliser d'entiers - le cas échéant .Il est donc parfaitement «sûr» et approprié de l'utiliser
MONEY
lorsque vous traitezMONEY
et de l'utiliser selon les règles mathématiques qu'il suit (commeINT
eger).Aurait-il été préférable que SQL Server promeuve la division et la multiplication des
MONEY
s enDECIMAL
s (ouFLOAT
s?) - peut-être, mais ils n'ont pas choisi de le faire; ils n'ont pas non plus choisi de promouvoir lesINT
egers enFLOAT
s lors de leur division.MONEY
n'a pas de problème de précision; cela permetDECIMAL
d'avoir un type intermédiaire plus grand utilisé pendant les calculs n'est qu'une «fonctionnalité» de l'utilisation de ce type (et je ne suis pas vraiment sûr de l'étendue de cette «fonctionnalité»).Pour répondre à la question spécifique, une "raison impérieuse"? Eh bien, si vous voulez des performances maximales absolues dans un
SUM(x)
oùx
pourrait être l'unDECIMAL
ou l' autreMONEY
, alors vousMONEY
aurez un avantage.N'oubliez pas non plus qu'il s'agit d'un cousin plus petit -
SMALLMONEY
juste 4 octets, mais il atteint son maximum214,748.3647
- ce qui est assez petit pour de l'argent - et n'est donc pas souvent un bon choix.Pour prouver l'intérêt d'utiliser des types intermédiaires plus grands, si vous affectez explicitement l'intermédiaire à une variable,
DECIMAL
le même problème se produit:Produit
2950.0000
(d'accord, donc au moinsDECIMAL
arrondi plutôt queMONEY
tronqué, comme un entier.)la source
MONEY
est un octet de moins qu'un grandDECIMAL
, avec jusqu'à 19 chiffres de précision. Cependant, la plupart des calculs monétaires réels (jusqu'à 9,99 M $) peuvent tenir dans unDECIMAL(9, 2)
, qui ne nécessite que cinq octets. Vous pouvez économiser de la taille, vous soucier moins des erreurs d'arrondi et rendre votre code plus portable.Nous venons de rencontrer un problème très similaire et je suis maintenant très bien un +1 pour ne jamais utiliser Money sauf dans la présentation de haut niveau. Nous avons plusieurs tableaux (en fait un bon de vente et une facture de vente), chacun contenant un ou plusieurs champs Money pour des raisons historiques, et nous devons effectuer un calcul au prorata pour déterminer la proportion de la facture totale que la taxe est pertinente pour chacun. ligne sur le bon de vente. Notre calcul est
Il en résulte un calcul réel argent / argent qui provoque des erreurs d'échelle sur la partie de division, qui se multiplient ensuite dans une proportion de TVA incorrecte. Lorsque ces valeurs sont ajoutées par la suite, nous nous retrouvons avec une somme des proportions de TVA qui ne correspondent pas à la valeur totale de la facture. Si l'une des valeurs entre parenthèses avait été décimale (je suis sur le point de transposer l'une d'entre elles en tant que telle), la proportion de TVA serait correcte.
Lorsque les crochets n'étaient pas là à l'origine, cela fonctionnait, je suppose qu'en raison des valeurs plus importantes impliquées, cela simulait effectivement une échelle plus élevée. Nous avons ajouté les crochets parce qu'il effectuait d'abord la multiplication, ce qui dans certains cas rares soufflait la précision disponible pour le calcul, mais cela a maintenant causé cette erreur beaucoup plus courante.
la source
En contrepoint de l'orientation générale des autres réponses. Voir les nombreux avantages de l'argent… Type de données! dans le Guide du moteur relationnel de SQLCAT
Plus précisément, je voudrais souligner ce qui suit
La réponse à la question est donc "ça dépend". Vous devez être plus prudent avec certaines opérations arithmétiques pour préserver la précision, mais vous constaterez peut-être que des considérations de performances en valent la peine.
la source
Je veux donner une vision différente de MONEY par rapport à NUMERICAL, en grande partie basée sur ma propre expertise et mon expérience ... Mon point de vue ici est MONEY, parce que je travaille avec lui depuis longtemps et que je n'ai jamais beaucoup utilisé NUMERICAL. .
MONEY Pro:
Type de données natif . Il utilise un type de données natif ( entier ) identique à un registre CPU (32 ou 64 bits), donc le calcul n'a pas besoin de surcharge inutile donc il est plus petit et plus rapide ... L'ARGENT a besoin de 8 octets et NUMÉRIQUE (19, 4 ) a besoin de 9 octets (12,5% plus gros) ...
L'ARGENT est plus rapide tant qu'il est utilisé car il devait l'être (en argent). À quelle vitesse? Mon simple
SUM
test sur 1 million de données montre que MONEY est de 275 ms et NUMERIC de 517 ms ... C'est presque deux fois plus rapide ... Pourquoi le test SUM? Voir le prochain point ProARGENT Con:
money
n'a pas besoin d'être aussi précis et est destiné à être utilisé comme de l'argent, pas seulement un nombre...Mais ... Gros, mais voici même votre application impliquée en argent réel, mais ne l'utilisez pas dans de nombreuses opérations SUM, comme en comptabilité. Si vous utilisez à la place de nombreuses divisions et multiplications, vous ne devez pas utiliser ARGENT ...
la source
money
colonneTous les messages précédents apportent des points valables, mais certains ne répondent pas précisément à la question.
La question est la suivante: pourquoi quelqu'un préférerait-il l'argent alors que nous savons déjà qu'il s'agit d'un type de données moins précis et peut provoquer des erreurs s'il est utilisé dans des calculs complexes?
Vous utilisez de l'argent lorsque vous ne ferez pas de calculs complexes et pouvez échanger cette précision pour d'autres besoins.
Par exemple, lorsque vous n'avez pas à effectuer ces calculs et que vous devez importer des données à partir de chaînes de texte de devise valides. Cette conversion automatique fonctionne uniquement avec le type de données MONEY:
Je sais que vous pouvez créer votre propre routine d'importation. Mais parfois, vous ne voulez pas recréer une routine d'importation avec des formats régionaux spécifiques au monde.
Un autre exemple, lorsque vous n'avez pas à faire ces calculs (vous avez juste besoin de stocker une valeur) et que vous devez économiser 1 octet (l'argent prend 8 octets et la décimale (19,4) prend 9 octets). Dans certaines applications (CPU rapide, grande RAM, IO lente), comme la lecture d'une énorme quantité de données, cela peut aussi être plus rapide.
la source
Vous ne devez pas utiliser d'argent lorsque vous devez faire des multiplications / divisions sur la valeur. L'argent est stocké de la même manière qu'un entier est stocké, tandis que le nombre décimal est stocké sous la forme d'un point décimal et de chiffres décimaux. Cela signifie que l'argent perdra sa précision dans la plupart des cas, tandis que la décimale ne le fera que lorsqu'elle sera reconvertie à son échelle d'origine. L'argent est un point fixe, donc son échelle ne change pas pendant les calculs. Cependant, comme il s'agit d'un point fixe lorsqu'il est imprimé sous forme de chaîne décimale (par opposition à une position fixe dans une chaîne de base 2), les valeurs jusqu'à l'échelle de 4 sont représentées exactement. Donc, pour l'addition et la soustraction, l'argent va bien.
Une décimale est représentée en base 10 en interne, et donc la position du point décimal est également basée sur le nombre de base 10. Ce qui fait que sa partie fractionnaire représente exactement sa valeur, tout comme avec de l'argent. La différence est que les valeurs intermédiaires de décimales peuvent maintenir la précision jusqu'à 38 chiffres.
Avec un nombre à virgule flottante, la valeur est stockée en binaire comme s'il s'agissait d'un entier, et la position du point décimal (ou binaire, ahem) est relative aux bits représentant le nombre. Parce qu'il s'agit d'un point décimal binaire, les nombres en base 10 perdent leur précision juste après le point décimal. 1 / 5ème, ou 0,2, ne peut pas être représenté précisément de cette manière. Ni l'argent ni les décimales ne souffrent de cette limitation.
Il est assez facile de convertir de l'argent en décimal, d'effectuer les calculs, puis de stocker la valeur résultante dans un champ ou une variable monétaire.
De mon POV, je veux que les choses qui arrivent aux nombres se produisent sans avoir à trop y penser. Si tous les calculs vont être convertis en décimales, alors pour moi, je voudrais simplement utiliser des décimales. Je conserverais le champ de l'argent à des fins d'affichage.
En termes de taille, je ne vois pas assez de différence pour changer d'avis. L'argent prend 4 à 8 octets, tandis que la décimale peut être 5, 9, 13 et 17. Les 9 octets peuvent couvrir toute la plage que peuvent contenir les 8 octets. Par index (la comparaison et la recherche doivent être comparables).
la source
J'ai trouvé une raison d'utiliser la décimale sur l'argent dans le sujet de précision.
DecimalResult> 1.000000
MoneyResult> 0.9999
FloatResult> 1
Testez-le et prenez votre décision.
la source
Je viens de voir cette entrée de blog: Money vs. Decimal dans SQL Server .
Ce qui dit essentiellement que l'argent a un problème de précision ...
Pour le
money
type, vous obtiendrez 19.30 au lieu de 19.34. Je ne sais pas s'il existe un scénario d'application qui divise l'argent en 1000 parties pour le calcul, mais cet exemple expose certaines limites.la source
money
etsmallmoney
sont exacts au dix millième des unités monétaires qu'ils représentent.» comme indiqué dans msdn.microsoft.com/en-us/library/ms179882.aspx, donc quiconque dit "ce sont des ordures" ne sait pas de quoi il parle.