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

Node.js Sequelize中DOUBLE(10,2)返回整数问题求解

问题:Sequelize中DOUBLE/DECIMAL类型字段补零格式化输出

在Node.js的Sequelize框架中,使用DataTypes.DOUBLE(10,2)或DataTypes.DECIMAL(10,2)定义字段时,会出现这样的情况:当字段值小数部分为0时返回整数(如2400),仅小数部分非0时才返回带小数的数值(如2400.5)。需求是让base_fare字段无论是否有小数部分,都输出2400.00这类保留两位小数的格式。

提供的迁移文件代码

'use strict';
module.exports = {
  async up(queryInterface, Sequelize) {
    await queryInterface.createTable('properties', {
      id: {
        allowNull: false,
        autoIncrement: true,
        primaryKey: true,
        type: Sequelize.INTEGER
      },
      serial: {
        type: Sequelize.INTEGER,
        allowNull: false,
      },
      name: {
        type: Sequelize.STRING,
      },
      type: {
        type: Sequelize.STRING,
        allowNull: false,
      },
      base_fare: {
        type: Sequelize.DOUBLE(10,2)
      },
      current_fare : {
        type: Sequelize.DOUBLE(10,2)
      },
      tenant_id: {
        type: Sequelize.INTEGER,
      },
      booking_id : {
        type: Sequelize.INTEGER
      },
      building_id : {
        type: Sequelize.INTEGER,
        allowNull: false,
        onDelete: 'CASCADE',
      }
    });
  },
  async down(queryInterface, Sequelize) {
    await queryInterface.dropTable('properties');
  }
};

提供的模型文件代码

'use strict';
const {
  Model
} = require('sequelize');
module.exports = (sequelize, DataTypes) => {
  class Property extends Model {
    static associate(models) {
     // Removed for readability
    }
  }

  Property.init({
    serial: DataTypes.INTEGER,
    type: DataTypes.STRING,
    name: DataTypes.STRING,
    base_fare: DataTypes.DOUBLE(10,2),
    current_fare: DataTypes.DOUBLE(10,2),
    tenant_id: DataTypes.INTEGER,
    booking_id: DataTypes.INTEGER,
    building_id: DataTypes.INTEGER,
  }, {
    sequelize,
    modelName: 'Property',
    timestamps: false,
    omitNull: false,
    name: {
      singular: 'property',
      plural: 'properties'
    },
    underscored: true
  });
  return Property;
};

示例数据

{
            "id": 11,
            "serial": 19,
            "type": "",
            "name": "Room",
            "base_fare": 2400,
            "current_fare": null,
            "tenant_id": null,
            "booking_id": null,
            "building_id": 1
},
{
            "id": 12,
            "serial": 19,
            "type": "",
            "name": "Room",
            "base_fare": 2400.5,
            "current_fare": null,
            "tenant_id": null,
            "booking_id": null,
            "building_id": 1
}

解决方案

方法一:给字段添加getter函数格式化输出

直接在模型的字段定义中添加getter逻辑,对返回值进行格式化:

Property.init({
  // ...其他字段
  base_fare: {
    type: DataTypes.DOUBLE(10,2),
    get() {
      const value = this.getDataValue('base_fare');
      // 若值存在则保留两位小数,否则返回null
      return value ? value.toFixed(2) : null;
    }
  },
  current_fare: {
    type: DataTypes.DOUBLE(10,2),
    get() {
      const value = this.getDataValue('current_fare');
      return value ? value.toFixed(2) : null;
    }
  },
  // ...其他字段
}, {
  // ...模型配置
});

注意:toFixed(2)会将数值转为字符串,如果需要保持数值类型,可改用parseFloat(value.toFixed(2)),但这样2400.00会变回2400,若必须显示两位小数,建议保留字符串类型或在前端做处理。

方法二:新增虚拟字段专门返回格式化值

如果不想修改原字段的返回格式,可以添加虚拟字段来输出格式化后的结果:

Property.init({
  // ...原有字段
  formatted_base_fare: {
    type: DataTypes.VIRTUAL,
    get() {
      const value = this.getDataValue('base_fare');
      return value ? value.toFixed(2) : null;
    }
  },
  // ...其他字段
}, {
  // ...模型配置
});

查询时直接获取formatted_base_fare字段即可得到格式化后的结果。

方法三:查询时用SQL函数格式化

在数据库层面直接处理格式化,不同数据库对应函数不同:

  • MySQL使用FORMAT函数:
const properties = await Property.findAll({
  attributes: [
    'id', 'serial', 'type', 'name',
    [sequelize.fn('FORMAT', sequelize.col('base_fare'), 2), 'base_fare'],
    'current_fare', 'tenant_id', 'booking_id', 'building_id'
  ]
});
  • PostgreSQL使用TO_CHAR函数:
const properties = await Property.findAll({
  attributes: [
    'id', 'serial', 'type', 'name',
    [sequelize.fn('TO_CHAR', sequelize.col('base_fare'), '99999999.99'), 'base_fare'],
    'current_fare', 'tenant_id', 'booking_id', 'building_id'
  ]
});

额外建议:优先用DECIMAL处理金额

金额类字段建议使用DataTypes.DECIMAL(10,2)替代DOUBLE,因为DOUBLE是浮点数存在精度丢失风险,DECIMAL是精确小数类型更适合金额场景。只需修改迁移文件和模型中的字段类型即可:
迁移文件:

base_fare: {
  type: Sequelize.DECIMAL(10,2)
},
current_fare : {
  type: Sequelize.DECIMAL(10,2)
}

模型文件:

base_fare: DataTypes.DECIMAL(10,2),
current_fare: DataTypes.DECIMAL(10,2),

内容的提问来源于stack exchange,提问作者Rafat Rashid Rahi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 03:10:45