Node、Express、MySQL2应用中SQL查询绑定参数错误问题咨询
先搞懂SQL参数绑定(参数化查询)的机制
当你在mysql2里用connection.execute(sql, params)执行查询时,这里的params就是绑定参数数组,对应SQL语句里的?占位符。这种方式叫参数化查询,核心优势有两个:
- 彻底规避SQL注入风险,驱动会自动对参数做转义处理
- 让SQL逻辑和业务数据分离,代码更清晰易维护
mysql2对绑定参数有严格要求:绝对不能传入undefined。因为它没法区分你是不小心漏传了参数,还是想传入SQL的NULL值。如果要表示SQL中的NULL,必须显式传入JS的null,否则就会抛出你遇到的这个错误。
排查你的问题根源
看你的代码,报错出在solarData.js的getMultiple函数里的绑定参数:
const rows = await db.query( `SELECT * FROM DTP LIMIT ?,?`, [offset, config.listPerPage] );
其中config.listPerPage是从环境变量LIST_PER_PAGE读取的,如果这个环境变量没设置,config.listPerPage就会是undefined。而offset是通过helper.getOffset(page, config.listPerPage)计算出来的,如果config.listPerPage是undefined,offset也大概率会变成undefined或者NaN(取决于你的helper.getOffset实现)。这两个值只要有一个是undefined,就会触发mysql2的报错。
具体解决方案
1. 给配置项添加默认值,避免undefined
修改config.js里的listPerPage配置,确保即使环境变量没设置,也有合法的默认值:
const config = { db: { host: env.SUNNY_HOST, user: env.SUNNY_USER, password: env.SUNNY_PW, database: env.SUNNY_DB, }, listPerPage: parseInt(env.LIST_PER_PAGE) || 10, // 加默认值10,同时转成数字类型 };
这里用parseInt确保值是数字(环境变量读出来都是字符串),|| 10在环境变量不存在或无效时用默认值兜底。
2. 双重保险:在业务函数里校验参数
在solarData.js的getMultiple函数里,先对page和listPerPage做合法性校验,避免无效值传入:
async function getMultiple(page = 1){ // 确保page是有效数字,默认1 const currentPage = parseInt(page) > 0 ? parseInt(page) : 1; // 再次确认每页数量是有效数字,避免配置出错 const listPerPage = parseInt(config.listPerPage) > 0 ? parseInt(config.listPerPage) : 10; const offset = helper.getOffset(currentPage, listPerPage); const rows = await db.query( `SELECT * FROM DTP LIMIT ?,?`, [offset, listPerPage] ); const data = helper.emptyOrRows(rows); const meta = {page: currentPage}; return { data, meta } }
3. 检查helper.js的getOffset实现
确保getOffset不会返回undefined或NaN,标准实现应该是这样的:
function getOffset(page, listPerPage) { // 提前校验参数,避免计算错误 if (typeof page !== 'number' || typeof listPerPage !== 'number') { return 0; } return (page - 1) * listPerPage; }
额外提醒
如果之后你需要在参数中传递SQL NULL(比如某个可选查询条件没值),记得用JS的null而不是undefined,比如:
// 假设要查询某个日期之后的数据,如果date参数不存在就查所有 const queryDate = req.query.date ? new Date(req.query.date) : null; const rows = await db.query( `SELECT * FROM DTP WHERE date >= ? OR ? IS NULL`, [queryDate, queryDate] );
内容的提问来源于stack exchange,提问作者Greg

