insertar - tipos de datos en sql server
Almacenar dinero en una columna decimal: ¿qué precisión y escala? (10)
4 lugares decimales le daría la precisión para almacenar las subunidades de divisas más pequeñas del mundo. Puede reducirlo aún más si necesita precisión de micropago (nanopayment ?!).
Yo también prefiero DECIMAL
a los tipos de dinero específicos de DBMS, es más seguro mantener ese tipo de lógica en la aplicación IMO. Otro enfoque en la misma línea es simplemente usar un entero [largo], con formato en ¤unit.subunit para la legibilidad humana (¤ = símbolo de moneda) hecho en el nivel de la aplicación.
Estoy usando una columna decimal para almacenar valores de dinero en una base de datos, y hoy me preguntaba qué precisión y escala usar.
Dado que supuestamente las columnas char de un ancho fijo son más eficientes, estaba pensando que lo mismo podría ser cierto para las columnas decimales. ¿Lo es?
¿Y qué precisión y escala debería usar? Estaba pensando en precisión 24/8. ¿Es eso excesivo, no es suficiente o está bien?
Esto es lo que he decidido hacer:
- Almacene las tasas de conversión (cuando corresponda) en la tabla de transacciones en sí, como un flotador
- Almacene la moneda en la tabla de cuentas
- El monto de la transacción será un
DECIMAL(19,4)
- Todos los cálculos que usan una tasa de conversión serán manejados por mi aplicación, por lo que mantengo el control de los problemas de redondeo
No creo que un factor flotante para la tasa de conversión sea un problema, ya que es principalmente para referencia, y de todos modos lo voy a convertir en un decimal.
Gracias a todos por su valiosa contribución.
A veces necesitarás ir a menos de un centavo y hay monedas internacionales que usan demoniaciones muy grandes. Por ejemplo, puede cobrar a sus clientes 0.088 centavos por transacción. En mi base de datos Oracle, las columnas se definen como NUMBER (20,4)
Creo que, en gran parte, sus requisitos o los de su cliente deberían dictar qué precisión y escala usar. Por ejemplo, para el sitio web de comercio electrónico en el que estoy trabajando que trata con dinero solo en libras esterlinas, se me ha requerido que lo mantenga en Decimal (6, 2).
Cuando maneje dinero en MySQL, use DECIMAL (13,2) si conoce la precisión de los valores de su dinero o use DOUBLE si solo desea un valor aproximado suficientemente rápido. Entonces, si su aplicación necesita manejar valores monetarios de hasta un billón de dólares (o euros o libras), entonces esto debería funcionar:
DECIMAL(13, 2)
O, si necesita cumplir con GAAP , use:
DECIMAL(13, 4)
El tipo de datos money en SQL Server tiene cuatro dígitos después del decimal.
De los libros en línea de SQL Server 2000:
Los datos monetarios representan cantidades de dinero positivas o negativas. En Microsoft® SQL Server ™ 2000, los datos monetarios se almacenan utilizando los tipos de datos money y smallmoney. Los datos monetarios se pueden almacenar con una precisión de cuatro decimales. Utilice el tipo de datos monetarios para almacenar valores en el rango de -922,337,203,685,477.5808 a +922,337,203,685,477.5807 (requiere 8 bytes para almacenar un valor). Utilice el tipo de datos smallmoney para almacenar valores en el rango de -214,748.3648 a 214,748.3647 (requiere 4 bytes para almacenar un valor). Si se requiere un mayor número de decimales, use el tipo de datos decimales en su lugar.
Recientemente implementamos un sistema que necesita manejar valores en múltiples monedas y convertir entre ellos, y resuelto algunas cosas de la manera más difícil.
NUNCA USE NÚMEROS DE PUNTOS FLOTANTES POR DINERO
La aritmética de punto flotante introduce imprecisiones que pueden no notarse hasta que hayan arruinado algo. Todos los valores se deben almacenar como enteros o como tipos decimales fijos, y si elige usar un tipo de decimal fijo, entonces asegúrese de entender exactamente qué hace ese tipo bajo el capó (es decir, ¿usa internamente un número entero o un punto flotante? tipo).
Cuando necesita hacer cálculos o conversiones:
- Convertir valores a punto flotante
- Calcular nuevo valor
- Redondea el número y conviértelo de nuevo a un número entero
Al convertir un número de coma flotante de nuevo a un número entero en el paso 3, no lo lances: utiliza una función matemática para redondearlo primero. Esto generalmente será round
, aunque en casos especiales podría ser floor
o ceil
. Sepa la diferencia y elija cuidadosamente.
Almacene el tipo de un número junto con el valor
Esto puede no ser tan importante para usted si solo maneja una divisa, pero fue importante para nosotros en el manejo de varias monedas. Usamos el código de 3 caracteres para una moneda, como USD, GBP, JPY, EUR, etc.
Dependiendo de la situación, también puede ser útil almacenar:
- Si el número es antes o después de impuestos (y cuál fue la tasa de impuestos)
- Si el número es el resultado de una conversión (y de qué se convirtió)
Conozca los límites de precisión de los números con los que está tratando
Para valores reales, quiere ser tan preciso como la unidad más pequeña de la moneda. Esto significa que no tiene valores menores que un centavo, un centavo, un yen, un fen, etc. No almacene valores con mayor precisión que eso sin ningún motivo.
Internamente, puede elegir tratar con valores más pequeños, en cuyo caso ese es un tipo diferente de valor de moneda . Asegúrese de que su código sepa cuál es el que no los mezcla. Evite usar valores de coma flotante incluso aquí.
Al sumar todas esas reglas, decidimos las siguientes reglas. En el código de ejecución, las monedas se almacenan utilizando un número entero para la unidad más pequeña.
class Currency {
String code; // eg "USD"
int value; // eg 2500
boolean converted;
}
class Price {
Currency grossValue;
Currency netValue;
Tax taxRate;
}
En la base de datos, los valores se almacenan como una cadena en el siguiente formato:
USD:2500
Eso almacena el valor de $ 25.00. Pudimos hacerlo solo porque el código que trata con las monedas no necesita estar dentro de la capa de la base de datos, por lo que todos los valores se pueden convertir primero en memoria. Otras situaciones sin duda se prestarán a otras soluciones.
Y en caso de que no lo haya aclarado antes, ¡no use float!
Si está buscando una talla única para todos, le sugiero que DECIMAL(19, 4)
es una opción popular (un Google rápido lo confirma). Creo que esto proviene del antiguo tipo de datos VBA / Access / Jet Currency, siendo el primer tipo decimal de punto fijo en el lenguaje; Decimal
solo entró en el estilo ''versión 1.0'' (es decir, no se implementó por completo) en VB6 / VBA6 / Jet 4.0.
La regla general para el almacenamiento de valores decimales de punto fijo es almacenar al menos un lugar decimal más de lo que realmente necesita para permitir el redondeo. Uno de los motivos para mapear el antiguo tipo de Currency
en el anverso al DECIMAL(19, 4)
en el extremo posterior era que Currency
exhibía redondeo bancario por naturaleza, mientras que DECIMAL(p, s)
redondeaba por truncamiento.
Un decimal adicional almacenado para DECIMAL
permite implementar un algoritmo de redondeo personalizado en lugar de tomar los valores predeterminados del proveedor (y el redondeo bancario es alarmante, por decir lo menos, para un diseñador que espera que todos los valores que terminan en .5 redondeen desde cero )
Sí, DECIMAL(24, 8)
suena exagerado. La mayoría de las monedas se cotizan en cuatro o cinco lugares decimales. Sé de situaciones en las que se requiere una escala decimal de 8 (o más) pero aquí es donde se ha prorrateado una cantidad monetaria ''normal'' (digamos cuatro decimales), lo que implica que la precisión decimal debe reducirse en consecuencia (también considere un tipo de coma flotante en tales circunstancias). Y nadie tiene tanto dinero hoy en día para requerir una precisión decimal de 24 :)
Sin embargo, en lugar de un enfoque único para todos, algunas investigaciones pueden estar en orden. Pregúntele a su diseñador o experto de dominio sobre reglas contables que pueden ser aplicables: PCGA, UE, etc. Recuerdo vagamente algunas transferencias dentro de la UE con reglas explícitas para redondear a cinco lugares decimales, por lo tanto usando DECIMAL(p, 6)
para almacenamiento. Los contadores generalmente parecen favorecer cuatro decimales.
PD: Evite el tipo de datos MONEY
SQL Server porque tiene graves problemas de precisión al redondear, entre otras consideraciones, como la portabilidad, etc. Consulte el blog de Aaron Bertrand .
Los diseñadores de Microsoft y de lenguaje eligieron el redondeo bancario porque los diseñadores de hardware lo eligieron [¿citación?]. Está consagrado en los estándares del Instituto de Ingenieros Eléctricos y Electrónicos (IEEE), por ejemplo. Y los diseñadores de hardware lo eligieron porque los matemáticos lo prefieren. Ver Wikipedia ; parafraseando: La edición de 1906 de Probability and Theory of Errors llamó a esto "la regla de la computadora" ("computadoras" significa humanos que realizan cálculos).
Si estuviera utilizando IBM Informix Dynamic Server, tendría un tipo MONEY que es una variante menor en el tipo DECIMAL o NUMERIC. Siempre es un tipo de punto fijo (mientras que DECIMAL puede ser un tipo de coma flotante). Puede especificar una escala de 1 a 32, y una precisión de 0 a 32 (por defecto a una escala de 16 y una precisión de 2). Entonces, dependiendo de lo que necesite almacenar, puede usar DECIMAL (16,2) - aún lo suficientemente grande para mantener el Déficit Federal de los EE. UU., Al centavo más cercano - o puede usar un rango menor o más decimales.
Si vas a hacer cualquier tipo de operaciones aritméticas en el DB (multiplicando las tasas de facturación, etc.), es probable que desees mucha más precisión de la que la gente sugiere aquí, por las mismas razones que nunca lo harías. desea usar algo menos que un valor de punto flotante de precisión doble en el código de la aplicación.
Una respuesta tardía aquí, pero he usado
DECIMAL(13,2)
lo cual estoy en lo cierto al pensar que debería permitir hasta 99.999.999.999,99.