如何在Sequelize查询中正确使用FLOAT数值类型?
在Sequelize中正确查询FLOAT类型字段的问题
问题描述
我在Sequelize里定义了带FLOAT类型字段的数据模型,查询时遇到了类型转换的坑:
模型定义代码:
const Stat = sequelize.define('stat', { ID : { type: DataTypes.INTEGER, allowNull: false }, displayName: { type: DataTypes.STRING, allowNull: false }, shortName : { type: DataTypes.STRING, allowNull: false }, value : { type: DataTypes.FLOAT(10, 1), allowNull: false } }, { freezeTableName: true, timestamps: false })
执行查询的代码:
const test = await Stat.findOne({ where: { shortName: shortName, value : 22.1 }, attributes: ['displayName', 'shortName', 'value'] })
结果生成的SQL把数值22.1转成了字符串,导致匹配不到数据库里的FLOAT类型值:
SELECT `displayName`, `shortName`, `value` FROM `stat` AS `stat` WHERE `stat`.`shortName` = 'TC' AND `stat`.`value` = '22.1' LIMIT 1;
我想要的是把条件作为数值传入,生成这样的SQL:
SELECT `displayName`, `shortName`, `value` FROM `stat` AS `stat` WHERE `stat`.`shortName` = 'TC' AND `stat`.`value` = 22.1 LIMIT 1;
自己临时找到了一个解决办法,但感觉不够稳妥,想听听大家的意见:
const test = await Stat.findOne({ attributes: ['displayName', 'shortName', 'value'], where: { shortName: shortName, value: sequelize.literal(`value = ${value}`) } })
更优解决方案
方案1:用操作符+类型转换明确指定数值类型
借助Sequelize的Op.eq操作符配合cast方法,强制让参数以FLOAT类型传入:
const { Op } = require('sequelize'); const test = await Stat.findOne({ attributes: ['displayName', 'shortName', 'value'], where: { shortName: shortName, value: { [Op.eq]: sequelize.cast(22.1, 'FLOAT') } } });
方案2:检查Sequelize与数据库驱动版本
这种字符串自动转换的问题,大概率是Sequelize版本和数据库驱动的兼容性问题。建议升级到Sequelize v6+版本,同时使用mysql2(而非旧版mysql)作为MySQL驱动,新版本对数值类型的参数绑定处理更准确。
方案3:改进你自己的literal方案,避免SQL注入
你当前用sequelize.literal直接拼接数值存在SQL注入风险,如果value是用户输入的变量,很容易被恶意利用。可以改成参数绑定的写法:
const test = await Stat.findOne({ attributes: ['displayName', 'shortName', 'value'], where: sequelize.literal(`shortName = ? AND value = ?`, [shortName, 22.1]) });
或者用命名参数的方式:
const test = await Stat.findOne({ attributes: ['displayName', 'shortName', 'value'], where: sequelize.literal(`shortName = :shortName AND value = :value`), replacements: { shortName, value: 22.1 } });
总结
优先选方案1,既能保证类型匹配,又能规避安全风险;同时检查Sequelize和驱动版本,从根源上解决类型绑定的问题。
内容的提问来源于stack exchange,提问作者Akihiro
相关产品推荐
相关产品推荐

