PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

Données monétaires sur PostgreSQL avec Java

NUMERIC /DECIMAL

Comme l'a dit Joachim Isaksson , vous souhaitez utiliser NUMERIC /DECIMAL type, en tant que type de précision arbitraire.

Deux points importants à propos de NUMERIC /DECIMAL :

  • Lire la doc soigneusement pour apprendre que vous devez spécifier l'échelle pour éviter l'échelle par défaut de 0, c'est-à-dire des valeurs entières où la fraction décimale est supprimée. Bien que ce soit l'un des endroits où Postgres s'écarte du SQL standard (vous donnant toute échelle jusqu'à la limite d'implémentation). Ne pas spécifier l'échelle est donc un mauvais choix.
  • Les types SQL NUMERIC &DECIMAL sont proches mais pas identiques selon la norme SQL. Dans SQL:92 , votre précision spécifiée pour NUMERIC est respecté, alors que pour DECIMAL le serveur de base de données est autorisé à ajouter une précision supplémentaire au-delà de ce que vous avez spécifié. Ici encore Postgres s'éloigne un peu du standard, avec à la fois NUMERIC &DECIMAL documenté comme équivalent.

Conditions :

  • La précision correspond au nombre total de chiffres dans un nombre.
  • L'échelle est le nombre de chiffres à droite de la virgule (la fraction décimale).
  • ( Précision - Échelle ) =Nombre de chiffres à gauche de la virgule (partie entière).

Soyez clair sur les spécifications de votre projet en matière de précision et d'échelle :

  • Gros
    La précision doit être suffisamment grande pour gérer des nombres plus importants qui pourraient être nécessaires à l'avenir. Ce qui signifie… Peut-être que votre application fonctionne aujourd'hui pour des milliers d'USD, mais qu'à l'avenir, elle devra générer des rapports cumulatifs qui se chiffreront en millions.
  • Petit
    Pour certaines raisons comptables, vous devrez peut-être stocker une fraction du plus petit montant en devise. Ce qui signifie… Plus de 3 ou 4 décimales plutôt que les 2 nécessaires pour un sou en USD .

Évitez MONEY taper

Postgres offre un MONEY tapez aussi. Cela peut sembler juste, mais probablement pas le meilleur pour la plupart des objectifs. Un inconvénient est qu'avec MONEY l'échelle est définie par un paramètre de configuration à l'échelle de la base de données basé sur locale . Ainsi, ce paramètre peut varier dangereusement facilement lorsque vous changez de serveur ou apportez d'autres modifications. De plus, vous ne pouvez pas contrôler ce paramètre pour des colonnes spécifiques, tandis que vous pouvez définir l'échelle sur chaque colonne de NUMERIC taper. Enfin, MONEY n'est pas du SQL standard comme indiqué dans cette liste de données SQL standard type . Postgres inclut MONEY pour la commodité des personnes transférant des données à partir d'autres systèmes de base de données.

Déplacer la virgule décimale

Une autre alternative employée par certains consiste à déplacer la virgule décimale et à simplement stocker dans un grand type de données entier.

Par exemple, si vous stockez USD dollars au centime, multipliez n'importe quel nombre fractionnaire donné par 100, transformez-le en un type entier et continuez. Par exemple, 123,45 $ devient l'entier 12 345.

L'avantage de cette approche est des temps d'exécution plus rapides. Opérations telles que sum sont très rapides lorsqu'ils sont exécutés sur des nombres entiers. Un autre avantage des nombres entiers est la moindre utilisation de la mémoire.

Je trouve cette approche ennuyeuse, déroutante et risquée. Ennuyeux parce que les ordinateurs devraient fonctionner pour nous, pas contre nous. Risqué parce que certains programmeurs ou utilisateurs peuvent négliger de multiplier/diviser pour reconvertir en nombre fractionnaire, donnant des résultats incorrects. Si vous travaillez dans un système sans une bonne prise en charge des nombres fractionnaires précis, cette approche peut être une solution de contournement acceptable.

Je ne vois aucun avantage à déplacer la virgule décimale quand on a DECIMAL /NUMERIC en SQL et BigDecimal en Java.

Arrondi &NaN

Dans la programmation de votre application, ainsi que dans tous les calculs effectués côté serveur Postgres, soyez très prudent et conscient des arrondis et des troncatures dans la fraction décimale. Et testez les NaNs par inadvertance surgissant.

Des deux côtés, app et Postgres, évitez toujours virgule flottante types de données pour le travail monétaire. La virgule flottante est conçue pour la vitesse de performance , mais au prix de la précision . Les calculs peuvent entraîner des chiffres supplémentaires apparemment fous dans la fraction décimale. Pas bon pour les finances/l'argent ou à d'autres fins où la précision compte.

BigDecimal

Oui, en Java, vous voulez BigDecimal comme type de précision arbitraire. BigDecimal est plus lent et utilise plus de mémoire, mais stockera avec précision vos montants d'argent. SQL NUMERIC /DECIMAL devrait correspondre à BigDecimal comme indiqué ici et sur StackOverflow .

BigDecimal est l'une des meilleures choses à propos de Java. Je ne connais aucune autre plate-forme avec une classe similaire, en particulier une si bien implémentée et bien rodée avec des améliorations et des corrections majeures apportées au fil des ans.

Utilisation de BigDecimal est certainement plus lent que d'utiliser les types à virgule flottante de Java , float &double . Mais dans les applications du monde réel, je doute que vos calculs d'argent soient un goulot d'étranglement. Et d'ailleurs, que voulez-vous ou vos clients :le plus rapide calculs d'argent, ou précis calculs d'argent? 😉

J'ai toujours pensé à BigDecimal en tant que plus grande fonctionnalité dormante de Java, l'avantage le plus important de l'utilisation de la plate-forme Java par rapport à tant d'autres plates-formes dépourvues d'une prise en charge aussi sophistiquée des nombres fractionnaires.

Question similaire :Meilleur type de données pour la devise