You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Waterline ORM(Sails.js)如何指定decimal类型长度精度存储货币值

Waterline ORM(Sails + PostgreSQL)货币字段配置方案

一、货币值存储的最佳选型

  • 不推荐用float类型存储货币:浮点数基于二进制实现,天生存在精度截断问题,做金额累加、折扣计算时很容易出现0.1+0.2=0.30000000000000004这类误差,支付、对账场景下会直接造成资损问题。
  • 存储层优先选用decimal(9,2):你当前配置的这个PostgreSQL原生类型本身完全符合货币存储要求,固定保留2位小数,最大支持存储9999999.99的金额,覆盖绝大多数普通法币的业务场景完全够用。
  • 你碰到的blueprints查询返回字符串不是功能异常,是sails-postgresql适配器的默认处理逻辑:JavaScript原生Number类型无法无损承载高精度十进制值,适配器为了避免精度丢失,会把decimal/numeric类型的查询结果默认转成字符串返回。只需要在模型里加简单的转换逻辑,就能正常返回数字类型,不需要修改columnType配置。
    转换配置参考:
    attributes: { 
      price: {
        type: 'number',
        columnType: 'decimal(9,2)',
        columnName: 'PRICE',
        // 查询结果转数字返回
        after: function(val) {
          return val === null ? null : Number(val);
        },
        // 写入前统一处理为2位小数格式
        before: function(val) {
          if (typeof val !== 'number' || isNaN(val)) return val;
          return val.toFixed(2);
        }
      }
    }
    
    如果业务涉及超大金额、多币种需要更高精度,也可以直接存分为单位的整数,比如10.00元存1000,用integer类型,完全没有精度问题,计算性能也更好,只需要在业务层做元分转换即可,这也是工业界非常常用的落地方案。

二、float类型映射decimal(9,2)存储的配置方法

  • 只要显式指定columnType: 'decimal(9,2)',不管属性的type设为number还是float,sails-postgresql都会在数据库里创建decimal(9,2)格式的字段,不会自动转成浮点数类型。配置示例:
    attributes: { 
      price: {
        type: 'float',
        columnType: 'decimal(9,2)',
        columnName: 'PRICE'
      }
    }
    
  • 注意:如果只写type: 'float'不指定columnType,适配器会默认创建双精度浮点数(double precision)类型字段,不会自动使用decimal类型,必须手动声明columnType才能固定为decimal(9,2)的存储格式。
  • 非必要不推荐该搭配:用float类型映射decimal字段时,JS侧的浮点数精度问题依然存在,就算数据库存的是固定2位小数,转成JS浮点数后做计算还是可能出现精度漂移。

内容的提问来源于stack exchange,提问作者S. Kaushika

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 16:54:07