sql >> Base de Datos >  >> RDS >> PostgreSQL

Datos de dinero en PostgreSQL usando Java

NUMERIC /DECIMAL

Como dijo Joachim Isaksson , desea usar NUMERIC /DECIMAL type, como un tipo de precisión arbitraria.

Dos puntos importantes sobre NUMERIC /DECIMAL :

  • Lea el doc detenidamente para saber que debe especificar la escala para evitar la escala predeterminada de 0, es decir, valores enteros donde la fracción decimal se corta. Si bien este es uno de los lugares donde Postgres se desvía del SQL estándar (lo que le brinda una escala hasta el límite de implementación). Por lo tanto, no especificar la escala es una mala elección.
  • Los tipos SQL NUMERIC &DECIMAL son cercanos pero no idénticos según el estándar SQL. En SQL:92 , su precisión especificada para NUMERIC se respeta, mientras que para DECIMAL el servidor de la base de datos puede agregar precisión adicional más allá de lo que especificó. Aquí nuevamente, Postgres se desvía un poco del estándar, con ambos NUMERIC &DECIMAL documentado como equivalente.

Términos:

  • La precisión es el número total de dígitos en un número.
  • La escala es el número de dígitos a la derecha del punto decimal (la fracción decimal).
  • ( Precisión - Escala ) =Número de dígitos a la izquierda del punto decimal (parte entera).

Sea claro en las especificaciones de precisión y escala de su proyecto:

  • Grande
    La precisión debe ser lo suficientemente grande para manejar números más grandes que puedan ser necesarios en el futuro. Es decir... Tal vez su aplicación funcione hoy en cantidades de miles de dólares, pero en el futuro deberá realizar informes acumulativos que terminen en millones.
  • Pequeño
    Para algunos fines contables, es posible que deba almacenar una fracción de la cantidad de moneda más pequeña. Es decir… Más de 3 o 4 decimales en lugar de los 2 necesarios para un centavo en USD .

Evite MONEY escribir

Postgres ofrece un MONEY tipo también. Eso puede sonar bien, pero probablemente no sea lo mejor para la mayoría de los propósitos. Una desventaja es que con MONEY la escala se establece mediante una configuración de toda la base de datos basado en locale . Por lo tanto, esa configuración puede variar peligrosamente fácilmente cuando cambia de servidor o realiza otros cambios. Además, no puede controlar esa configuración para columnas específicas, mientras que puede establecer la escala en cada columna de NUMERIC escribe. Por último, MONEY no es SQL estándar como se muestra en esta lista de datos SQL estándar tipos . Postgres incluye MONEY para la comodidad de las personas que transfieren datos de otros sistemas de bases de datos.

Mover el punto decimal

Otra alternativa empleada por algunos es mover el punto decimal y simplemente almacenarlo en un tipo de datos entero grande.

Por ejemplo, si almacena USD dólares al centavo, multiplique cualquier número fraccionario dado por 100, convierta a un tipo entero y continúe. Por ejemplo, $123,45 se convierte en el número entero 12 345.

El beneficio de este enfoque es tiempos de ejecución más rápidos. Operaciones como sum son muy rápidos cuando se realizan en números enteros. Otro beneficio de los números enteros es un menor uso de memoria.

Encuentro este enfoque molesto, confuso y arriesgado. Molesto porque las computadoras deberían estar trabajando para nosotros, no contra nosotros. Arriesgado porque algún programador o usuario puede olvidarse de multiplicar/dividir para convertir de nuevo a número fraccionario, dando resultados incorrectos. Si trabaja en un sistema sin un buen soporte para números fraccionarios precisos, este enfoque podría ser una solución alternativa aceptable.

No veo ninguna ventaja en mover el punto decimal cuando tenemos DECIMAL /NUMERIC en SQL y BigDecimal en Java.

Redondeo y NaN

En la programación de su aplicación, así como en cualquier cálculo realizado en el lado del servidor de Postgres, tenga mucho cuidado y tenga cuidado con el redondeo y el truncamiento. en la fracción decimal. Y prueba para NaNs involuntarios apareciendo.

En ambos lados, aplicación y Postgres, siempre evite punto flotante tipos de datos para el trabajo de dinero. El punto flotante está diseñado para velocidad de rendimiento , pero a costa del costo de precisión . Los cálculos pueden resultar en dígitos adicionales aparentemente locos en la fracción decimal. No es bueno para fines financieros/dinero u otros fines donde la precisión es importante.

BigDecimal

Sí, en Java, desea BigDecimal como su tipo de precisión arbitraria. BigDecimal es más lento y utiliza más memoria, pero almacenará con precisión las cantidades de dinero. SQL NUMERIC /DECIMAL debe asignarse a BigDecimal como se comenta aquí y en StackOverflow .

BigDecimal es una de las mejores cosas de Java. No conozco ninguna otra plataforma con una clase similar, especialmente una tan bien implementada y perfeccionada con importantes mejoras y correcciones realizadas a lo largo de los años.

Usando BigDecimal es definitivamente más lento que usar los tipos de punto flotante de Java , float &double . Pero en las aplicaciones del mundo real, dudo que sus cálculos de dinero sean un cuello de botella. Y además, qué es lo que tú o tus clientes queréis:el más rápido cálculos de dinero, o precisos calculos de dinero? 😉

Siempre he pensado en BigDecimal como la función durmiente más grande en Java, la ventaja más importante de usar la plataforma Java sobre tantas otras plataformas que carecen de un soporte tan sofisticado para números fraccionarios.

Pregunta similar:Mejor tipo de datos para moneda