sql-server - type - varchar(max)




Devriez-vous choisir les types de données MONEY ou DECIMAL(x, y) dans SQL Server? (8)

Comme un contrepoint à la poussée 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 soulignerais ce qui suit

En travaillant sur les implémentations des clients, nous avons trouvé des chiffres de performance intéressants concernant le type de données money. Par exemple, lorsque Analysis Services a été défini sur le type de données de devise (à partir du double) pour correspondre au type de données money SQL Server, il y a eu une amélioration de 13% de la vitesse de traitement (lignes / s). Pour obtenir des performances plus rapides dans SQL Server Integration Services (SSIS) pour charger 1,18 To en moins de trente minutes, comme indiqué dans SSIS 2008 - Performances ETL du record mondial, il a été observé que la modification des quatre colonnes décimales (9,2) avec une taille de 5 octets dans la table TPC-H LINEITEM à l'argent (8 octets) amélioré la vitesse d'insertion en vrac de 20% ... La raison de l'amélioration des performances est due au protocole TDS (Tabular Data Stream) de SQL Server, qui a le principe clé pour transférer des données sous forme binaire compacte et aussi proche que possible du format de stockage interne de SQL Server. Empiriquement, ceci a été observé lors du test de performance ETL record du monde de SSIS 2008 en utilisant Kernrate; le protocole a chuté de manière significative lorsque le type de données a été remplacé par de l'argent 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 processeur supplémentaires à gérer par rapport à un type à largeur fixe.

Donc la réponse à la question est "ça dépend". Vous devez être plus prudent avec certaines opérations arithmétiques pour préserver la précision, mais vous pouvez trouver que les considérations de performance en valent la peine.

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

Je suis conscient que l' money est spécifique à SQL Server. Ce que je veux savoir, c'est 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 de l' money et non des decimal pour des choses comme les informations de prix.

Devrais-je simplement continuer à utiliser le type de données money ou y a-t-il un avantage à utiliser decimal à la place? L'argent est moins de caractères à taper mais ce n'est pas une raison valable :)


Eh bien, j'aime l' 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 excellent avertissement pour les ignorants - pourrait également être appliqué aux INT egers, où le résultat serait nul. Mais ce n'est pas une raison pour ne pas utiliser d'entiers - le cas échéant .

Donc, il est parfaitement 'sûr' et approprié d'utiliser l' MONEY quand ce que vous avez affaire est MONEY et utilisez-le selon les règles mathématiques qui en découlent (comme INT eger).

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

MONEY n'a aucun problème de précision; que les DECIMAL obtiennent un type intermédiaire plus grand utilisé pendant les calculs est juste une 'caractéristique' de l'utilisation de ce type (et je ne suis pas vraiment sûr de savoir jusqu'où s'étend cette 'fonctionnalité').

Pour répondre à la question spécifique, une «raison impérieuse»? Eh bien, si vous voulez une performance maximale absolue dans un SUM(x)x pourrait être soit DECIMAL ou MONEY , alors MONEY aura un avantage.

De plus, n'oubliez pas que c'est un cousin plus petit, SMALLMONEY -juste 4 octets, mais il fait un maximum de 214,748.3647 - ce qui est plutôt petit pour l'argent - et n'est donc pas souvent un bon ajustement.

Pour prouver le point d'utilisation de types intermédiaires plus grands, si vous affectez explicitement l'intermédiaire à 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 (d'accord, donc au moins DECIMAL arrondi plutôt que MONEY tronqué-même qu'un entier serait.)


Jamais vous ne devriez utiliser de l'argent, ce n'est pas précis et c'est de la pure poubelle, utilisez toujours décimal / numérique

lance ça 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

Rendement: 2949.0000 2949.8525

Pour certaines des personnes qui ont dit que vous ne divisez pas l'argent en argent

Voici une de mes requêtes pour calculer les corrélations, changer cela en argent donne des résultats erronés

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

Je me rends compte que WayneM a déclaré qu'il sait que l'argent est spécifique à SQL Server. Cependant, il demande s'il y a des raisons d'utiliser l'argent au-dessus de la décimale et vice versa et je pense qu'une raison évidente doit encore être indiquée et que l'utilisation de décimales signifie que c'est une chose de moins à s'inquiéter si jamais vous devez changer votre SGBD - Ce qui peut arriver.

Rendez vos systèmes aussi flexibles que possible!


Je viens de voir cette entrée ... http://thavash.spaces.live.com/blog/cns!CF6232111374DFD2!223.entry

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 d'argent, vous obtiendrez 19.30 au lieu de 19.34. Je ne suis pas sûr s'il existe un scénario d'application qui divise l'argent en 1000 parties pour le calcul, mais cet exemple expose certaines limitations.

Harsha


Nous venons de rencontrer un problème très similaire et je suis maintenant un +1 pour ne jamais utiliser d'argent, sauf dans la présentation de haut niveau. Nous avons plusieurs tables (en réalité un bon de vente et une facture de vente) contenant chacune un ou plusieurs champs Money pour des raisons historiques, et nous devons effectuer un calcul au prorata pour déterminer quelle partie de la facture totale 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)

Cela se traduit par un calcul réel argent / argent qui provoque des erreurs d'échelle sur la partie de la division, qui se multiplie ensuite dans une proportion incorrecte de la cuve. Lorsque ces valeurs sont ensuite ajoutées, nous obtenons une somme des proportions de la cuve qui ne correspond 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 en tant que telle), la proportion de la cuve serait correcte.

Lorsque les parenthèses n'étaient pas là, cela fonctionnait à l'origine, je suppose qu'en raison des valeurs plus importantes, cela simulait effectivement une échelle plus élevée. Nous avons ajouté les crochets car il faisait d'abord la multiplication, ce qui dans de rares cas soufflait la précision disponible pour le calcul, mais cela a maintenant causé cette erreur beaucoup plus commune.


Vous ne devriez 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 la décimale est stockée sous la forme d'un point décimal et de chiffres décimaux. Cela signifie que l'argent perdra de sa précision dans la plupart des cas, tandis que la décimale ne le fera que lorsqu'il sera reconverti à son échelle d'origine. L'argent est un point fixe, donc son échelle ne change pas pendant les calculs. Cependant, parce que c'est un point fixe quand il est imprimé en tant que 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 sa valeur exactement, comme avec de l'argent. La différence est que les valeurs intermédiaires de la décimale 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. 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 la décimale ne souffrent de cette limitation.

Il est assez facile de convertir 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 point de vue, je veux que les choses qui arrivent aux nombres se produisent sans avoir à y réfléchir trop. Si tous les calculs vont être convertis en décimales, alors pour moi je voudrais juste utiliser la décimale. Je voudrais enregistrer le champ d'argent à des fins d'affichage.

Du point de vue de la 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 gamme que les 8 octets d'argent peuvent. Index-sage (comparaison et recherche devrait être comparable).


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 journée:

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 d' money sont des entiers

Les représentations textuelles de smallmoney et decimal(10,4) peuvent se ressembler, mais cela ne les rend pas interchangeables. Avez-vous grincer des dents lorsque vous voyez des dates stockées comme 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 textuelle de l' money est fluff visuel, tout comme les tirets dans une date aaaa-mm-jj. SQL ne les stocke pas réellement en interne.

En ce qui concerne la decimal rapport à l' money , choisissez ce qui est approprié pour vos besoins. Les types d' money existent parce que le stockage des valeurs comptables en tant que multiples entiers de 1 / 10000e d'unité est très commun. 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'arrondissement des banquiers (IEEE 754)





types