Devez-vous choisir les types de données argent ou décimal(x,y) dans SQL Server?

je suis curieux de savoir s'il y a ou non une différence réelle entre le type de données money et quelque chose comme decimal(19,4) (ce qui est ce que l'argent utilise à l'interne, je crois).

je suis conscient que money est spécifique au serveur SQL. Je veux savoir s'il y a une raison impérieuse de choisir l'un plutôt que l'autre; la plupart des échantillons de Serveur SQL (par exemple la base de données AdventureWorks) utilisent money et non decimal pour des choses comme l'information de prix.

dois-je continuer à utiliser le type de données monétaires, ou y a-t-il un avantage à utiliser la décimale à la place? De l'argent est de moins en moins de caractères à taper, mais ce n'est pas une raison valable :)

362
demandé sur Peter Mortensen 2009-02-24 20:54:38

12 réponses

Ne jamais utiliser d'argent. Il n'est pas exact, et c'est un pur ordures; toujours utiliser décimal/numérique.

exécutez ceci pour voir ce que je veux dire:

DECLARE
    @mon1 MONEY,
    @mon2 MONEY,
    @mon3 MONEY,
    @mon4 MONEY,
    @num1 DECIMAL(19,4),
    @num2 DECIMAL(19,4),
    @num3 DECIMAL(19,4),
    @num4 DECIMAL(19,4)

    SELECT
    @mon1 = 100, @mon2 = 339, @mon3 = 10000,
    @num1 = 100, @num2 = 339, @num3 = 10000

    SET @mon4 = @mon1/@mon2*@mon3
    SET @num4 = @num1/@num2*@num3

    SELECT @mon4 AS moneyresult,
    @num4 AS numericresult

sortie: 2949.0000 2949.8525

à certains de ceux qui disent qu'on ne divise pas l'argent par l'argent:

Voici une de mes requêtes pour calculer les corrélations, et changer cela en argent donne de mauvais résultats.

select t1.index_id,t2.index_id,(avg(t1.monret*t2.monret)
    -(avg(t1.monret) * avg(t2.monret)))
            /((sqrt(avg(square(t1.monret)) - square(avg(t1.monret))))
            *(sqrt(avg(square(t2.monret)) - square(avg(t2.monret))))),
current_timestamp,@MaxDate
            from Table1 t1  join Table1 t2  on t1.Date = traDate
            group by t1.index_id,t2.index_id
259
répondu SQLMenace 2018-07-21 16:15:43

SQLMenace dit que l'argent est inexact. Mais vous n'avez pas multiplier/diviser l'argent par l'argent! Combien font 3 dollars x 50 cents? 150 dollarcents? Vous multipliez/divisez l'argent par scalars, qui devrait être décimal.

DECLARE
@mon1 MONEY,
@mon4 MONEY,
@num1 DECIMAL(19,4),
@num2 DECIMAL(19,4),
@num3 DECIMAL(19,4),
@num4 DECIMAL(19,4)

SELECT
@mon1 = 100,
@num1 = 100, @num2 = 339, @num3 = 10000

SET @mon4 = @mon1/@num2*@num3
SET @num4 = @num1/@num2*@num3

SELECT @mon4 AS moneyresult,
@num4 AS numericresult

donne le résultat correct:

moneyresult           numericresult
--------------------- ---------------------------------------
2949.8525             2949.8525

money est bon aussi longtemps que vous n'avez pas besoin de plus de 4 chiffres après la virgule, et vous vous assurez que votre scalaires - qui ne représentent pas de l'argent - sont decimal .

250
répondu configurator 2009-02-24 18:09:44

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 le jour:

declare @num1 numeric(38,22)
declare @num2 numeric(38,22)
set @num1 = .0000006
set @num2 = 1.0
select @num1 * @num2 * 1000000

1.000000 < - devrait être 0.6000000


les types money sont des entiers

les représentations textuelles de smallmoney et decimal(10,4) peuvent se ressembler, mais cela ne les rend pas interchangeables. Est-ce que vous craquez quand vous voyez des dates stockées sous varchar(10) ? C'est la même chose.

dans les coulisses, money / smallmoney sont juste un bigint / int le point décimal dans la représentation de texte de money est fluff visuel, tout comme les tirets dans une date AAAA-mm-JJ. SQL ne les stocke pas en interne.

en ce qui concerne decimal vs money , choisissez ce qui est approprié pour vos besoins. Les types money existent parce que le stockage des valeurs comptables en multiples entiers de 1/10000th d'unité est très commun. En outre, si vous avez affaire à de l'argent réel et des calculs au-delà de simple addition et soustraction, vous ne devriez pas faire cela au niveau de la base de données! à Faire au niveau de l'application avec une bibliothèque qui prend en charge l'Arrondi (IEEE 754)

46
répondu Anon 2017-05-23 12:34:41

je me rends compte que WayneM a déclaré qu'il sait que l'argent est spécifique au serveur SQL. Cependant, il demande s'il y a des raisons d'utiliser l'argent sur Décimal ou vice versa et je pense qu'une raison évidente devrait encore être déclaré et qui est d'utiliser décimal signifie que c'est une chose de moins à se soucier si vous avez jamais à changer votre SGBD - ce qui peut se produire.

rendez vos systèmes aussi flexibles que possible!

37
répondu Dean 2012-08-13 00:28:10

J'aime bien MONEY ! C'est un octet moins cher que DECIMAL , et les calculs sont plus rapides parce que (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 s'appliquer aux INT egers, où le résultat serait zéro. Mais ce n'est pas une raison pour ne pas utiliser les entiers- où approprié .

donc, c'est parfaitement 'sûr' et approprié d'utiliser MONEY quand ce que vous traitez est MONEY et l'utiliser selon des règles mathématiques qu'il suit (même que INT eger).

aurait-il été préférable que SQL Server promeuve la division et la multiplication de MONEY 's en DECIMAL s (ou FLOAT s?)- peut-être, mais ils n'ont pas choisi de le faire; ils n'ont pas non plus choisi de promouvoir INT egers à FLOAT s en les divisant.

MONEY n'a pas de problème de précision; que DECIMAL s obtiennent d'avoir un plus grand type intermédiaire utilisé au cours des calculs est juste une "caractéristique" de l'utilisation de ce type (et je ne suis pas réellement sûr jusqu'à quel point cette "caractéristique" s'étend).

pour répondre À la question spécifique, une "raison impérieuse"? Si vous voulez des performances maximales absolues dans un SUM(x)x pourrait être soit DECIMAL ou MONEY , alors MONEY aura un bord.

aussi, n'oubliez pas qu'il est plus petit cousin, SMALLMONEY - seulement 4 octets, mais il ne max à 214,748.3647 - qui est assez petit pour l'argent-et donc n'est pas souvent une bonne taille.

pour prouver le point autour de l'utilisation de types intermédiaires plus grands, si vous assignez l'intermédiaire explicitement à une variable, DECIMAL souffre du même problème:

declare @a decimal(19,4)
declare @b decimal(19,4)
declare @c decimal(19,4)
declare @d decimal(19,4)

select @a = 100, @b = 339, @c = 10000

set @d = @a/@b

set @d = @d*@c

select @d

produit 2950.0000 (bon, donc au moins DECIMAL arrondi plutôt que MONEY tronqué-même qu'un entier le ferait.)

30
répondu dsz 2013-11-11 20:37:06

comme contrepoint à l'orientation générale des autres réponses. Voir les nombreux avantages de L'Argent...Type de données! in SQLCAT Guide to Relational Engine

en particulier, je voudrais souligner ce qui suit

en travaillant sur les implémentations des clients, nous avons trouvé quelque chose d'intéressant les chiffres relatifs à la performance concernant le type de données monétaires. Par exemple, lorsque Les services d'analyse ont été type de données monétaire (double) correspondent au type de données argent du serveur SQL, il y avait une amélioration de 13% dans la vitesse de traitement (lignes/sec). Pour obtenir des performances plus rapides au sein de SQL Services D'intégration de serveurs (SSIS) pour charger 1.18 TB en moins de trente procès-verbal, tel que noté dans SSIS 2008 - world record ETL performance, il a été a observé que le changement des quatre colonnes décimales(9,2) avec une taille de 5 octets dans le TPC-H LINEITEM table à l'argent (8 octets) s'est améliorée en vrac vitesse d'insertion de 20%... Raison pour l'amélioration de la performance est en raison de SQL protocole de flux de données tabulaires (TDS) du serveur, qui a le principe de conception clé pour transférer des données sous forme binaire compacte et aussi proche que possible du stockage interne format de SQL Server. Empiriquement, cela a été observé lors du test de performance ETL SSIS 2008 - world record en utilisant Kernrate; le protocole a chuté de manière significative lorsque le type de données a été commuté à l'argent de décimal. Cela rend le transfert de données aussi efficace que possible. Un type de données complexe nécessite des cycles D'analyse et de CPU supplémentaires à gérer qu'un de type à Largeur fixe.

ainsi la réponse à la question Est"cela dépend". Vous devez être plus prudent avec certaines opérations arithmétiques pour préserver la précision, mais vous trouverez peut-être que des considérations de performance rendent cela utile.

12
répondu Martin Smith 2016-07-24 10:42:31

nous venons de tomber sur une question très similaire et je suis maintenant très a +1 pour ne jamais utiliser l'argent sauf dans la présentation de haut niveau. Nous avons plusieurs tables (en fait un bon de vente et une facture de vente) dont chacune contient un ou plusieurs champs D'argent pour des raisons historiques, et nous devons effectuer un calcul au prorata pour déterminer combien de la taxe totale sur les factures est pertinente pour chaque ligne sur le bon de vente. Notre calcul est

vat proportion = total invoice vat x (voucher line value / total invoice value)

ce résultat dans un calcul monnaie / monnaie réel qui provoque des erreurs d'échelle sur la partie de division, qui se multiplie alors dans une proportion de TVA incorrecte. Lorsque ces valeurs sont ajoutées par la suite, nous obtenons une somme des proportions de TVA qui ne correspondent pas à la valeur totale de la facture. Si l'une ou l'autre des valeurs entre parenthèses était une décimale (je suis sur le point de lancer l'une d'entre elles comme telle) la proportion de TVA serait correcte.

quand les consoles n'étaient pas là à l'origine, cela servait à le travail, je suppose qu'en raison des plus grandes valeurs impliquées, il simulait efficacement une échelle plus élevée. Nous avons ajouté les parenthèses parce qu'il faisait la multiplication d'abord, qui dans certains cas rares souffrait la précision disponible pour le calcul, mais cela a maintenant causé cette erreur beaucoup plus commune.

10
répondu Kaideejee 2011-11-21 02:03:47

je veux donner un point de vue différent de L'argent par rapport à numérique, largement basé sur ma propre expertise et expérience... Mon point de vue ici est L'argent, parce que j'ai travaillé avec lui pendant une longue période Et je n'ai jamais vraiment utilisé beaucoup numérique...

MONEY Pro:

  • Type De Données Natives . Il utilise un type de données natif ( entier ) comme le même que celui D'un registre CPU (32 ou 64 bits), donc le calcul n'a pas besoin de frais généraux inutiles donc c'est plus petit et plus rapide ... L'argent a besoin de 8 octets et le numérique (19, 4) a besoin de 9 octets (12,5% plus gros)...

    l'ARGENT est plus rapide aussi longtemps qu'il est utilisé pour les il était censé être (comme l'argent). À quelle vitesse? Mon test simple SUM sur 1 million de données montre que l'argent est de 275 ms et 517 ms numériques... C'est-à-dire presque deux fois plus rapide ... Pourquoi le test de la somme? Voir la prochaine Pro point

  • la Meilleure pour l'Argent . L'argent est mieux pour stocker l'argent et faire des opérations, par exemple, dans la comptabilité. Un seul rapport peut exécuter des millions d'additions (somme) et quelques multiplications après l'opération de somme. Pour les très grandes applications de comptabilité, il est presque deux fois plus rapide , et il est extrêmement important...
  • faible précision de De l'argent . L'argent dans la vraie vie n'a pas besoin d'être très précis. Je veux dire, beaucoup de gens peuvent se soucier de 1 cent USD, mais que diriez-vous de 0,01 cent USD? En fait, dans mon pays, les banques ne se soucient plus de cents (chiffre après virgule décimale); Je ne sais pas à propos de la banque américaine ou d'un autre pays...

de l'ARGENT Con:

  • Précision Limitée . L'argent n'a que quatre chiffres (après la virgule) de précision, il doit donc être converti avant de faire des opérations telles que la division... Mais là encore money n'a pas besoin d'être aussi précis et est destiné à être utilisé comme de l'argent, pas juste un numéro...

Mais... Grand, mais voici même votre application a impliqué de l'argent réel, mais ne l'utilisez pas dans beaucoup d'opérations de Somme, comme dans la comptabilité. Si vous utilisez beaucoup de divisions et de multiplications à la place, vous ne devriez pas utiliser l'argent...

5
répondu Susilo 2018-07-21 16:28:29

vous ne devriez pas utiliser l'argent quand vous avez besoin de faire des multiplications / divisions sur la valeur. L'argent est stocké de la même façon qu'un entier est stocké, tandis que décimal est stocké comme un point décimal et décimal chiffres. Cela signifie que l'argent va baisser la précision dans la plupart des cas, tandis que décimal ne le fera que lorsque converti de nouveau à son échelle d'origine. L'argent est un point fixe, de sorte que son échelle ne change pas pendant les calculs. Cependant parce que c'est un point fixe quand il est imprimé comme une 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 est bien.

une décimale est représentée en base 10 interne, et donc la position de la virgule est également basée sur le nombre de base 10. Ce qui fait que sa partie fractionnaire représente exactement sa valeur, comme avec l'argent. La différence est que les valeurs intermédiaires de décimal peuvent maintenir la précision jusqu'à 38 chiffres.

avec un nombre à virgule flottante, la valeur est stockée en binaire comme si elle était un entier, et la position du point décimal (OU binaire, ahem) est relative aux bits représentant le nombre. Comme il s'agit d'un point décimal binaire, les nombres de 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 souffrent de cette limitation.

Il est assez facile de convertir de l'argent à décimal, effectuer les calculs, puis stocker la valeur résultante de nouveau dans un champ d'argent ou variable.

de mon POV, je veux que les choses qui arrivent aux nombres se produisent sans avoir à leur donner trop de réflexion. Si tous les calculs doivent être convertis en décimales, alors pour moi, je voudrais juste utiliser décimales. J'économiserais l'argent pour l'étalage.

Taille-sage Je ne vois pas assez de différence pour changer d'avis. Argent prend 4 à 8 octets, alors que la décimale peut être 5, 9, 13, et 17. Les 9 octets peuvent couvrir la gamme entière que les 8 octets de l'argent peut. Du point de vue de l'indice (la comparaison et la recherche doivent être comparables).

2
répondu Gerard ONeill 2017-05-18 19:10:35

j'ai trouvé une raison sur l'utilisation décimale sur l'argent dans le sujet d'exactitude.

DECLARE @dOne   DECIMAL(19,4),
        @dThree DECIMAL(19,4),
        @mOne   MONEY,
        @mThree MONEY,
        @fOne   FLOAT,
        @fThree FLOAT

 SELECT @dOne   = 1,
        @dThree = 3,    
        @mOne   = 1,
        @mThree = 3,    
        @fOne   = 1,
        @fThree = 3

 SELECT (@dOne/@dThree)*@dThree AS DecimalResult,
        (@mOne/@mThree)*@mThree AS MoneyResult,
        (@fOne/@fThree)*@fThree AS FloatResult

il suffit de le tester et de prendre votre décision.

1
répondu QMaster 2014-01-21 11:49:00

je viens de voir cette entrée de blog: Argent vs. décimal dans SQL Server .

qui dit essentiellement que l'argent a un problème de précision...

declare @m money
declare @d decimal(9,2)

set @m = 19.34
set @d = 19.34

select (@m/1000)*1000
select (@d/1000)*1000

pour le type money , vous obtiendrez 19,30 au lieu de 19,34. Je ne suis pas sûr qu'il y ait un scénario d'application qui divise l'argent en 1000 parties pour le calcul, mais cet exemple expose certaines limites.

0
répondu Harsha 2018-07-21 16:18:23

tous les billets précédents apportent des points valables, mais certains ne répondent pas à la question précisément.

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 qu'il peut causer des erreurs s'il est utilisé dans des calculs complexes?

vous utilisez l'argent quand vous ne faites pas de calculs complexes et pouvez échanger cette précision pour d'autres besoins.

Par exemple, lorsque vous n'avez pas à faire ces calculs ci-dessus et besoin d'économiser 1 byte (l'argent prend 8 bytes et décimal(19,4) prend 9 bytes).

un autre exemple, quand vous n'avez pas à faire ces calculs ci-dessus et besoin de vitesse pour le traitement énorme quantité de données.

un autre exemple, quand vous n'avez pas à faire ces calculs ci-dessus, et avez besoin d'importer des chaînes de texte de devise valides. Essayez de faire cela avec d'autres types numériques: sélectionnez Convertir (argent, '$1,000.68')

0
répondu Weber K. 2018-07-22 22:35:41