Tengo curiosidad por saber si existe o no una diferencia real entre el money
tipo de datos y algo parecido decimal(19,4)
(que es lo que el dinero usa internamente, creo).
Soy consciente de que money
es específico de SQL Server. Quiero saber si hay una razón convincente para elegir uno sobre el otro; la mayoría de las muestras de SQL Server (por ejemplo, la base de datos AdventureWorks) usan money
y no decimal
para cosas como información de precios.
¿Debo seguir usando el tipo de datos de dinero, o hay un beneficio al usar decimal en su lugar? El dinero tiene menos caracteres para escribir, pero esa no es una razón válida :)
sql-server
types
Wayne Molina
fuente
fuente
DECIMAL(19, 4)
es una opción popular, verifique esto también marque aquí Formatos de moneda mundial para decidir cuántos lugares decimales usar, la esperanza ayuda.Respuestas:
Nunca deberías usar dinero. No es preciso, y es pura basura; siempre use decimal / numérico.
Ejecute esto para ver a qué me refiero:
Salida: 2949.0000 2949.8525
Para algunas de las personas que dijeron que no divide dinero por dinero:
Aquí está una de mis consultas para calcular correlaciones, y cambiar eso a dinero da resultados incorrectos.
fuente
money
másmoney
, esta 'ilustración' es manipuladora. Es un hecho documentado quemoney
tiene una precisión fija y muy limitada. En tales casos, primero se debe multiplicar y luego dividir. Cambie el orden de los operadores en este ejemplo y obtendrá resultados idénticos. Unmoney
esencialmente es un int de 64 bits, y si tuviera que lidiar con ints, se multiplicaría antes de dividir.SQLMenace dijo que el dinero es inexacto. ¡Pero no multiplica / divide dinero por dinero! ¿Cuánto es 3 dólares por 50 centavos? 150 centavos de dólar? Multiplicas / divides dinero por escalares, que deben ser decimales.
Resultados en el resultado correcto:
money
es bueno siempre que no necesite más de 4 dígitos decimales y se asegure de que sus escalares, que no representan dinero, seandecimal
s.fuente
money / money
? La respuesta es unidades enteras sin signo de dólar, ¡lo cual es correcto! Este es un escenario perfectamente razonable, lo que sugiere que debido a casos extremos extraños como este,money
no es un buen tipo de datos para usar, ya que el resultado siempre se trunca para que encaje enmoney
lugar de seguir las reglas normales de precisión y escala. ¿Qué sucede si desea calcular la desviación estándar de un conjunto demoney
valores? Sí,Sqrt(Sum(money * money))
(simplificado) en realidad tiene sentido.Todo es peligroso si no sabes lo que estás haciendo.
Incluso los tipos decimales de alta precisión no pueden salvar el día:
1.000000 <- Debe ser 0.6000000
Los
money
tipos son enteros.Las representaciones de texto de
smallmoney
ydecimal(10,4)
pueden parecerse, pero eso no las hace intercambiables. ¿Te estremeces cuando ves las fechas almacenadas comovarchar(10)
? Esto es lo mismo.Detrás de escena,
money
/smallmoney
son solo abigint
/int
El punto decimal en la representación de texto demoney
es pelusa visual, al igual que los guiones en una fecha aaaa-mm-dd. SQL en realidad no los almacena internamente.Con respecto a
decimal
vsmoney
, elija lo que sea apropiado para sus necesidades. Losmoney
tipos existen porque almacenar valores contables como múltiplos enteros de 1/10000 de unidad es muy común. Además, si se trata de dinero real y cálculos más allá de la simple suma y resta, ¡no debería hacerlo a nivel de base de datos! Hágalo a nivel de aplicación con una biblioteca que admita el redondeo bancario (IEEE 754)fuente
Me doy cuenta de que WayneM ha declarado que sabe que el dinero es específico de SQL Server. Sin embargo, está preguntando si hay alguna razón para usar el dinero en lugar del decimal o viceversa, y creo que aún se debe indicar una razón obvia y que usar el decimal significa que es una cosa menos de la que preocuparse si alguna vez tiene que cambiar su DBMS - Que puede suceder.
¡Haga que sus sistemas sean lo más flexibles posible!
fuente
date
tipo, yo diría que siempre tendrá esos problemas. Debería decir "No utilice tipos obsoletos cuando la base de datos ya proporciona tipos mejores y más compatibles con el estándar y advierte contra los obsoletos".Bueno, me gusta
MONEY
! Es un byte más barato queDECIMAL
, y los cálculos se realizan más rápido porque (debajo de las cubiertas) las operaciones de suma y resta son esencialmente operaciones enteras. El ejemplo de @ SQLMenace, que es una gran advertencia para los que no lo saben, podría aplicarse igualmente a losINT
egers, donde el resultado sería cero. Pero esa no es razón para no usar números enteros, cuando corresponda .Por lo tanto, es perfectamente 'seguro' y apropiado usarlo
MONEY
cuando se trata deMONEY
eso y usarlo de acuerdo con las reglas matemáticas que sigue (igual queINT
eger).¿Hubiera sido mejor si SQL Server promoviera la división y la multiplicación de
MONEY
's enDECIMAL
s (oFLOAT
s)? Posiblemente, pero no eligieron hacer esto; ni eligieron promoverINT
egers aFLOAT
s al dividirlos.MONEY
no tiene problemas de precisión; esoDECIMAL
de tener un tipo intermedio más grande usado durante los cálculos es solo una 'característica' de usar ese tipo (y en realidad no estoy seguro de hasta qué punto se extiende esa 'característica').Para responder a la pregunta específica, ¿una "razón convincente"? Bueno, si desea un rendimiento máximo absoluto en un lugar
SUM(x)
dondex
podría serDECIMAL
oMONEY
, entoncesMONEY
tendrá una ventaja.Además, no olvide que es un primo más pequeño, de solo
SMALLMONEY
4 bytes, pero tiene un máximo de214,748.3647
, que es bastante pequeño para el dinero, y por lo tanto no suele ser una buena opción.Para probar el punto usando tipos intermedios más grandes, si asigna el intermedio explícitamente a una variable,
DECIMAL
sufre el mismo problema:Produce
2950.0000
(bueno, al menosDECIMAL
redondeado en lugar deMONEY
truncado, igual que un entero).fuente
MONEY
es un byte menos que uno grandeDECIMAL
, con hasta 19 dígitos de precisión. Sin embargo, la mayoría de los cálculos monetarios del mundo real (hasta $ 9.99 M) pueden caber en unDECIMAL(9, 2)
, que requiere solo cinco bytes. Puede ahorrar tamaño, preocuparse menos por los errores de redondeo y hacer que su código sea más portátil.Acabamos de encontrarnos con un problema muy similar y ahora soy un +1 por nunca usar Money, excepto en la presentación de nivel superior. Tenemos varias tablas (efectivamente un comprobante de venta y una factura de venta), cada una de las cuales contiene uno o más campos de Dinero por razones históricas, y necesitamos realizar un cálculo prorrateado para determinar cuánto del Impuesto total de la factura es relevante para cada línea en el comprobante de venta. Nuestro cálculo es
Esto da como resultado un cálculo de dinero / dinero del mundo real que causa errores de escala en la parte de división, que luego se multiplica en una proporción de IVA incorrecta. Cuando estos valores se agregan posteriormente, terminamos con una suma de las proporciones de iva que no se suman al valor total de la factura. Si cualquiera de los valores entre paréntesis hubiera sido un decimal (estoy a punto de lanzar uno de ellos como tal), la proporción del iva sería correcta.
Cuando los corchetes no estaban allí originalmente, esto solía funcionar, supongo que debido a los valores más grandes involucrados, efectivamente estaba simulando una escala más alta. Agregamos los corchetes porque estaba haciendo la multiplicación primero, lo que en algunos casos raros sopló la precisión disponible para el cálculo, pero esto ahora ha causado este error mucho más común.
fuente
Como contrapunto al impulso general de las otras respuestas. Vea los muchos beneficios del dinero ... ¡Tipo de datos! en la Guía de SQLCAT para el motor relacional
Específicamente, señalaría lo siguiente
Entonces la respuesta a la pregunta es "depende". Debe tener más cuidado con ciertas operaciones aritméticas para preservar la precisión, pero puede encontrar que las consideraciones de rendimiento hacen que valga la pena.
fuente
Quiero dar una visión diferente de DINERO versus NUMÉRICO, basándome en gran medida en mi propia experiencia y experiencia ... Mi punto de vista aquí es DINERO, porque he trabajado con él durante mucho tiempo y nunca utilicé mucho NUMÉRICO. .
DINERO Pro:
Tipo de datos nativos . Utiliza un tipo de datos nativo ( entero ) igual que un registro de CPU (32 o 64 bits), por lo que el cálculo no necesita una sobrecarga innecesaria, por lo que es más pequeño y más rápido ... DINERO necesita 8 bytes y NUMÉRICO (19, 4 ) necesita 9 bytes (12.5% más grande) ...
El DINERO es más rápido siempre que se use para lo que estaba destinado (como dinero). ¿Qué rápido? Mi simple
SUM
prueba en 1 millón de datos muestra que el DINERO es 275 ms y NUMÉRICO 517 ms ... Eso es casi el doble de rápido ... ¿Por qué la prueba SUMA? Ver siguiente punto ProDINERO Con:
money
, no necesita ser tan preciso y debe usarse como dinero, no solo para número...Pero ... Grande, pero aquí incluso su aplicación involucra dinero real, pero no la use en muchas operaciones de SUM, como en contabilidad. Si usa muchas divisiones y multiplicaciones, entonces no debería usar DINERO ...
fuente
money
columnaTodas las publicaciones anteriores aportan puntos válidos, pero algunas no responden la pregunta con precisión.
La pregunta es: ¿por qué alguien preferiría el dinero cuando ya sabemos que es un tipo de datos menos preciso y puede causar errores si se usa en cálculos complejos?
Usas dinero cuando no haces cálculos complejos y puedes cambiar esta precisión por otras necesidades.
Por ejemplo, cuando no tiene que hacer esos cálculos y necesita importar datos de cadenas de texto de moneda válidas. Esta conversión automática solo funciona con el tipo de datos DINERO:
Sé que puedes hacer tu propia rutina de importación. Pero a veces no desea volver a crear una rutina de importación con formatos locales específicos en todo el mundo.
Otro ejemplo, cuando no tiene que hacer esos cálculos (solo necesita almacenar un valor) y necesita guardar 1 byte (el dinero toma 8 bytes y el decimal (19,4) toma 9 bytes). En algunas aplicaciones (CPU rápida, RAM grande, IO lenta), como leer una gran cantidad de datos, esto también puede ser más rápido.
fuente
No debe usar dinero cuando necesita hacer multiplicaciones / divisiones en el valor. El dinero se almacena de la misma manera que se almacena un número entero, mientras que el decimal se almacena como un punto decimal y dígitos decimales. Esto significa que el dinero disminuirá la precisión en la mayoría de los casos, mientras que el decimal solo lo hará cuando se vuelva a convertir a su escala original. El dinero es un punto fijo, por lo que su escala no cambia durante los cálculos. Sin embargo, debido a que es un punto fijo cuando se imprime como una cadena decimal (a diferencia de como una posición fija en una cadena de base 2), los valores hasta la escala de 4 se representan exactamente. Entonces, para sumar y restar, el dinero está bien.
Un decimal se representa en la base 10 internamente y, por lo tanto, la posición del punto decimal también se basa en el número de la base 10. Lo que hace que su parte fraccional represente exactamente su valor, al igual que con el dinero. La diferencia es que los valores intermedios de decimal pueden mantener una precisión de hasta 38 dígitos.
Con un número de coma flotante, el valor se almacena en binario como si fuera un número entero, y la posición del punto decimal (o binario, ejem) es relativa a los bits que representan el número. Debido a que es un punto decimal binario, los números de base 10 pierden precisión justo después del punto decimal. 1 / 5th, o 0.2, no se pueden representar con precisión de esta manera. Ni el dinero ni el decimal sufren esta limitación.
Es bastante fácil convertir dinero a decimal, realizar los cálculos y luego almacenar el valor resultante nuevamente en un campo o variable de dinero.
Desde mi POV, quiero que las cosas que suceden con los números sucedan sin tener que pensar demasiado en ellas. Si todos los cálculos se van a convertir a decimal, entonces para mí solo querría usar decimal. Guardaría el campo de dinero para mostrar.
En cuanto al tamaño, no veo suficiente diferencia para cambiar de opinión. El dinero toma de 4 a 8 bytes, mientras que el decimal puede ser 5, 9, 13 y 17. Los 9 bytes pueden cubrir todo el rango que pueden tener los 8 bytes de dinero. En cuanto al índice (comparar y buscar debe ser comparable).
fuente
Encontré una razón sobre el uso de decimal sobre dinero en materia de precisión.
Resultado decimal> 1.000000
MoneyResult> 0.9999
FloatResult> 1
Solo pruébalo y toma tu decisión.
fuente
Acabo de ver esta entrada de blog: Money vs. Decimal en SQL Server .
Lo que básicamente dice que el dinero tiene un problema de precisión ...
Para el
money
tipo, obtendrá 19.30 en lugar de 19.34. No estoy seguro de si existe un escenario de aplicación que divide el dinero en 1000 partes para el cálculo, pero este ejemplo expone algunas limitaciones.fuente
money
ysmallmoney
son precisos para una diezmilésima parte de las unidades monetarias que representan». como se dijo en msdn.microsoft.com/en-us/library/ms179882.aspx, por lo que cualquiera que diga "es basura" no sabe de qué está hablando.