¿Debería elegir los tipos de datos DINERO o DECIMAL (x, y) en SQL Server?

442

Tengo curiosidad por saber si existe o no una diferencia real entre el moneytipo de datos y algo parecido decimal(19,4)(que es lo que el dinero usa internamente, creo).

Soy consciente de que moneyes 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 moneyy no decimalpara 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 :)

Wayne Molina
fuente
12
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.
shaijut
Me preguntaba por qué el tipo de datos de dinero tiene 4 decimales ... y no 2. es decir, 100 centavos en un dólar, por lo que solo se requieren 2 decimales. Para almacenar un registro de cantidades de dinero inferiores a $ 9999.99, iba a ir con un tipo de datos decimal (6,2). No me preocupan los cálculos de dividir o multiplicar, solo el almacenamiento y la suma ..
Allan F

Respuestas:

326

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:

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

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.

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
SQLMenace
fuente
61
"Nunca" es una palabra fuerte. El "dinero" es útil para transmitir resultados a ese tipo para mostrar al usuario de una manera sensible a la cultura, pero tiene razón en que es muy malo usarlo para los cálculos en sí.
Joel Coehoorn
36
Su ejemplo no tiene sentido, ya que nadie nunca multiplicará dos objetos de tipo dinero. Si quieres probar tu punto, debes comparar multiplicar un dinero por un decimal para multiplicar un decimal por un decimal.
Brian
27
.. pero aún es sorprendente por qué el dinero * el dinero no tendría la precisión del dinero.
Aprendizaje
44
@Aprendizaje: tiene una precisión de dinero. Sin embargo, aún terminas con errores de redondeo que pueden acumularse con el tiempo. El tipo decimal no utiliza aritmética binaria: garantiza que obtenga los mismos resultados de base 10 que obtendría al hacerlo en papel.
Joel Coehoorn
55
Multiplicación y división de moneymás money, esta 'ilustración' es manipuladora. Es un hecho documentado que moneytiene 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. Un moneyesencialmente es un int de 64 bits, y si tuviera que lidiar con ints, se multiplicaría antes de dividir.
Andriy M
272

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.

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

Resultados en el resultado correcto:

resultado numérico
--------------------- ----------------------------- ----------
2949.8525 2949.8525

moneyes bueno siempre que no necesite más de 4 dígitos decimales y se asegure de que sus escalares, que no representan dinero, sean decimals.

configurador
fuente
57
¿Cuántas monedas de 1 centavo puede obtener un billete de un dólar? Una respuesta a esto requiere dinero / dinero.
Aprendizaje
48
@Aprendiendo en ese caso, el resultado no es dinero, sino un flotador. (Análisis dimensional básico.)
Richard
11
@Learning: ¿Le preguntas a la base de datos cuántos centavos por dólar? De todos modos, eso devolvería el resultado correcto. Su problema era que el dinero / dinero solo tenía una precisión de cuatro dígitos (era 0.2949), luego, cuando se multiplicaba por 10000, se convertía en 2949.0000.
configurador
26
@mson Él tiene razón y no hagas críticas personales como lo hiciste en base a un comentario de una línea, no es útil. Si no divide entre $ 0.01 sino 0.01, entonces el resultado es $ 100 en lugar de 100. Hay 100 centavos por dólar, no $ 100 centavos. Las unidades son importantes! Definitivamente hay un gran lugar para bucear, y tal vez multiplicar, dinero por dinero.
andrewb
19
Si quiero gastar $ 1000 para comprar acciones a un precio de $ 36, ¿no es un uso legítimo de 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, moneyno es un buen tipo de datos para usar, ya que el resultado siempre se trunca para que encaje en moneylugar de seguir las reglas normales de precisión y escala. ¿Qué sucede si desea calcular la desviación estándar de un conjunto de moneyvalores? Sí, Sqrt(Sum(money * money))(simplificado) en realidad tiene sentido.
ErikE
59

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:

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

1.000000 <- Debe ser 0.6000000


Los moneytipos son enteros.

Las representaciones de texto de smallmoneyy decimal(10,4)pueden parecerse, pero eso no las hace intercambiables. ¿Te estremeces cuando ves las fechas almacenadas como varchar(10)? Esto es lo mismo.

Detrás de escena, money/ smallmoneyson solo a bigint/ int El punto decimal en la representación de texto de moneyes pelusa visual, al igual que los guiones en una fecha aaaa-mm-dd. SQL en realidad no los almacena internamente.

Con respecto a decimalvs money, elija lo que sea apropiado para sus necesidades. Los moneytipos 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)

Luego
fuente
1
¿Puedes explicar lo que sucedió en este ejemplo?
Sergey Popov
44
Desbordamiento de escala. A escalas pequeñas, numérico (a, b) * numérico (c, d) produce numérico (a-b + c-d + 1, max (b, d)). Sin embargo, si (a + b + c + d)> 38, SQL limita la escala, robando precisión desde el lado de la fracción para rellenar el lado entero, causando el error de redondeo.
Anon
Todos los cálculos numéricos son susceptibles a la pérdida de precisión debido al escalado: en su lugar, seleccione select 1000000 * @ num1 * @ num2
Mitch Wheat
El ejemplo de Anon es la versión y la base de datos específicas. pero el punto tenga cuidado es válido. en sqlanywhere versión 1.1, el ejemplo da 0.600000 correctamente. (Sé que estamos hablando de ms sql aquí). Otro punto sobre el tipo de dinero que falta en otra base de datos, hay formas de llamar a decimal o numérico como dinero, como la creación de dominio.
gg89
3
Creo que esta es la respuesta más esclarecedora porque has explicado no solo los errores que se propagan, sino lo que realmente está sucediendo detrás de escena y por qué existe DINERO en primer lugar. No estoy seguro de por qué tardó 4 años en obtener esta respuesta, pero tal vez sea porque hay demasiado enfoque en el "problema" de cálculo, y no tanto en los por qué y cómo del dinero frente al decimal.
Steve Sether
44

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!

Decano
fuente
1
Posiblemente, pero en teoría podría declarar un dominio llamado Money en otro DBMS (que admita la declaración de dominios).
Debatador
Como alguien que actualmente está convirtiendo una base de datos de SQL Server a Amazon Redshift, puedo garantizar que este es un problema genuino. Trate de evitar los tipos de datos personalizados para una plataforma de base de datos en particular, a menos que haya razones comerciales muy sólidas para usarlos.
Nathan Griffiths
@Nathn dado el sistema de tipo débil de Redshift en comparación con PostgreSQL o SQL Server, por ejemplo, sin datetipo, 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".
Panagiotis Kanavos
@PanagiotisKanavos - el dinero no está en desuso
Martin Smith
@MartinSmith se sorprendió al ver esto, ya que en realidad no puede manejar valores monetarios como BTC en 2017. O diferenciar entre las cantidades de GBP y EUR, a pesar de que se mueven hacia la paridad: P. De todos modos, mudarse a Redshift introduce mucho dolor
Panagiotis Kanavos
32

Bueno, me gusta MONEY! Es un byte más barato que DECIMAL, 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 los INTegers, 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 MONEYcuando se trata de MONEYeso y usarlo de acuerdo con las reglas matemáticas que sigue (igual que INTeger).

¿Hubiera sido mejor si SQL Server promoviera la división y la multiplicación de MONEY's en DECIMALs (o FLOATs)? Posiblemente, pero no eligieron hacer esto; ni eligieron promover INTegers a FLOATs al dividirlos.

MONEYno tiene problemas de precisión; eso DECIMALde 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)donde xpodría ser DECIMALo MONEY, entonces MONEYtendrá una ventaja.

Además, no olvide que es un primo más pequeño, de solo SMALLMONEY4 bytes, pero tiene un máximo de 214,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, DECIMALsufre el mismo problema:

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

Produce 2950.0000(bueno, al menos DECIMALredondeado en lugar de MONEYtruncado, igual que un entero).

dsz
fuente
21
MONEYes un byte menos que uno grande DECIMAL , 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 un DECIMAL(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.
Si bien @JonofAllTrades es correcto, también puede recuperar el rendimiento de los enteros simplemente usando un entero que contenga centavos o centavos, y guarde el byte adicional que codifica la posición del punto decimal y que debe verificarse al agregar decimales juntos.
dsz
"Por lo tanto, es perfectamente 'seguro' y apropiado usar DINERO cuando se trata de DINERO y usarlo de acuerdo con las reglas matemáticas que sigue" -> sin embargo, vea también la respuesta de Anon: "Todo es peligroso si no lo hace saber lo que estás haciendo ". Nunca puede predecir cómo las personas terminarán consultando el sistema que está creando, lo mejor para evitar la posibilidad de mal uso cuando pueda. La ganancia minúscula en el almacenamiento no vale la pena en mi humilde opinión.
Nathan Griffiths
1
Intenta almacenar un valor de Bitcoin. Tiene 8 decimales
Panagiotis Kanavos
13

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

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

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.

Kaideejee
fuente
8
Pero solo lo hace porque un desarrollador ignorante ignoró las reglas para los cálculos del IVA y las limitaciones de precisión documentadas del dinero.
TomTom
1
@TomTom, pero lo que está diciendo sobre la posibilidad de mal uso de este tipo de datos es un argumento a favor de evitar usarlo en absoluto.
Nathan Griffiths
@Nathan No. Estoy señalando que el argumento dado como una razón para nunca usarlo es básicamente un desarrollador incompetente, por lo que el argumento es falso.
TomTom
1
@TomTom lamentablemente hay muchos desarrolladores incompetentes (así como muchos increíbles) y para mí, a menos que pueda garantizar cómo se consultarán estos datos en el futuro y nadie cometerá el tipo de errores descritos aquí , es mejor errar por precaución y usar un tipo decimal. Dicho esto, después de leer todas estas respuestas, puedo ver que hay algunos casos de uso específicos donde el dinero sería un tipo óptimo de uso, simplemente no lo usaría a menos que hubiera un muy buen caso de uso (por ejemplo, la columna solo alguna vez ser agregado por SUM, carga masiva de grandes cantidades de datos financieros).
Nathan Griffiths
@TomTom no son solo las limitaciones de precisión. La representación interna también puede causar problemas. El dinero es un tipo de conveniencia para atrapar a los desarrolladores ignorantes, no es un gran tipo que los desarrolladores estén usando mal. El ejemplo de iva, independientemente de las reglas para calcularlo, claramente debería ahuyentar a los desarrolladores no ignorantes cuando aplican lo específico al general.
Gerard ONeill
12

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

Trabajando en implementaciones de clientes, encontramos algunos números de rendimiento interesantes relacionados con el tipo de datos de dinero. Por ejemplo, cuando Analysis Services se configuró en el tipo de datos de moneda (del doble) para que coincida con el tipo de datos de dinero de SQL Server, hubo una mejora del 13% en la velocidad de procesamiento (filas / seg). Para obtener un rendimiento más rápido dentro de SQL Server Integration Services (SSIS) para cargar 1.18 TB en menos de treinta minutos, como se señaló en SSIS 2008 - rendimiento ETL récord mundial, se observó que al cambiar las cuatro columnas decimales (9,2) con un tamaño de 5 bytes en la tabla TPC-H LINEITEM a dinero (8 bytes) mejoraron la velocidad de inserción masiva en un 20% ... La razón de la mejora del rendimiento se debe al protocolo de flujo de datos tabulares (TDS) de SQL Server, que tiene el principio de diseño clave para transferir datos en forma binaria compacta y lo más cerca posible del formato de almacenamiento interno de SQL Server. Empíricamente, esto se observó durante el SSIS 2008: prueba de rendimiento ETL récord mundial con Kernrate; el protocolo cayó significativamente cuando el tipo de datos se cambió a dinero desde decimal. Esto hace que la transferencia de datos sea lo más eficiente posible. Un tipo de datos complejo necesita análisis y ciclos de CPU adicionales para manejar que un tipo de ancho fijo.

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.

Martin Smith
fuente
¿Cómo almacenarías bitcoin entonces?
Panagiotis Kanavos
@PanagiotisKanavos - No tengo idea. ¡Nunca he investigado Bitcoin y no sé prácticamente nada al respecto!
Martin Smith
6

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 SUMprueba 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 Pro

  • Lo mejor por dinero . El DINERO es mejor para almacenar dinero y realizar operaciones, por ejemplo, en contabilidad. Un solo informe puede ejecutar millones de adiciones (SUM) y algunas multiplicaciones después de que se realiza la operación SUM. Para aplicaciones de contabilidad muy grandes es casi el doble de rápido , y es extremadamente significativo ...
  • Baja precisión de dinero . El dinero en la vida real no necesita ser muy preciso. Quiero decir, a muchas personas les puede interesar alrededor de 1 centavo de dólar, pero ¿qué tal 0.01 centavo de dólar? De hecho, en mi país, a los bancos ya no les importan los centavos (dígito después de una coma decimal); No sé sobre el banco estadounidense u otro país ...

DINERO Con:

  • La precisión limitada . El DINERO solo tiene una precisión de cuatro dígitos (después de la coma), por lo que debe convertirse antes de realizar operaciones como la división ... Pero, de nuevo 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 ...

Susilo
fuente
1
Si va a decir que el dinero es más rápido que el decimal, debe decirnos cosas como qué rdbms, en qué hardware, qué sistema operativo, con qué datos específicos ejecutan qué consulta específica está hablando. Además, si no es COMPLETAMENTE exacto, NO estoy haciendo ninguna operación financiera con él, porque el recaudador de impuestos estará bastante disgustado por recuperar los números malos. Te importa el milésimo centavo si estás tratando con divisas estadounidenses, por ejemplo. Si el dinero no está haciendo eso, no es utilizable.
Haakon Løtveit
3
@ HaakonLøtveit todo este hilo de preguntas y respuestas trata sobre el tipo de datos "dinero" de SQL Server, por lo que no creo que necesiten especificar esto en la respuesta. El dinero puede ser más rápido de usar que el decimal en algunas circunstancias (por ejemplo, cargando datos), vea la respuesta de Martin Smith para más detalles. Estoy de acuerdo con la mayoría de esta respuesta, ya que hay ciertos casos de uso que pueden hacer que Money sea una opción más eficiente que el decimal, sin embargo, a menos que haya un caso muy convincente para usarlo, creo que debería evitarse.
Nathan Griffiths
1
Bitcoin tiene 8 decimales. Ni siquiera puedes almacenarlo en una moneycolumna
Panagiotis Kanavos
4

Todas 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:

SELECT CONVERT(MONEY, '$1,000.68')

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.

Weber K.
fuente
2

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).

Gerard ONeill
fuente
Gracias por el voto a favor. Estoy mirando esto y, mientras entiendo lo que estaba tratando de decir, también puedo ver que es muy confuso. Quizás lo volveré a escribir más tarde con algunos ejemplos de bit vs decimal.
Gerard ONeill
2

Encontré una razón sobre el uso de decimal sobre dinero en materia de precisión.

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

Resultado decimal> 1.000000

MoneyResult> 0.9999

FloatResult> 1

Solo pruébalo y toma tu decisión.

QMaster
fuente
2
Nos gustaría mucho escuchar (leer, es decir) su conclusión.
Peter Mortensen
@ PeterMortensen Creo que si quiero tener integridad y precisión entre los tipos de dinero y decimales, mi decisión debería ser decimal.
QMaster
1
Considere actualizar su respuesta con el resultado real de lo anterior. Entonces su conclusión será inmediatamente obvia para cualquiera que lea :-)
Agreax
1
@Ageax El resultado agregado a la respuesta.
QMaster
1

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 ...

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

set @m = 19.34
set @d = 19.34

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

Para el moneytipo, 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.

Harsha
fuente
15
No es un "problema", es "por especificaciones": «Los tipos de datos moneyy smallmoneyson 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.
Albireo