Express 结合 MySQL 开发API时rows返回undefined的问题排查
问题排查与修复方案
咱们一步步拆解你遇到的问题,先解决核心bug,再优化潜在的风险点:
1. 核心问题:SQL语法错误+参数绑定失效
你的按名称查询接口里,SQL语句存在两个致命问题,直接导致查询失败、rows返回undefined:
- MATCH AGAINST语法错误:正确的自然语言搜索语法是
MATCH(column) AGAINST(? IN NATURAL LANGUAGE MODE),你少写了MODE关键词,而且把参数直接拼进了SQL字符串,完全没用到mysql模块的参数绑定功能。 - 直接拼接参数的风险:用模板字符串把
req.params.name硬塞到SQL里,不仅会引发语法错误(比如产品名称含特殊字符时),还存在SQL注入风险,同时mysql的参数绑定机制完全没生效,导致查询执行失败。
2. 修复后的按名称查询接口代码
把SQL语句改成参数绑定的正确写法,同时修正语法,还优化了路由避免冲突:
app.get('/search/:name', (req, res, next)=>{ // 给路由加前缀,避免和其他路由误匹配 console.log('Fetching product with name: ' + req.params.name); const connection = getConnection(); // 正确使用占位符?,匹配参数绑定,同时修正MATCH AGAINST语法 const queryStr = 'SELECT * FROM products WHERE MATCH(name) AGAINST(? IN NATURAL LANGUAGE MODE)'; const modelName = req.params.name; connection.query( queryStr, [modelName], (err, rows, fields)=>{ connection.end(); // 务必关闭连接,避免连接池耗尽 if (err){ console.error('SQL查询出错:', err); // 打印错误日志,方便调试 res.status(500).send('<h1>500 Server Error</h1><h3>抱歉,服务器出现问题,我们正在处理!</h3>'); return; } console.log('查询结果:', rows); res.json(rows); } ) })
3. 其他潜在问题优化
- 路由顺序冲突:原来的
/:name是通用路由,会匹配所有没被前面路由捕获的请求(比如静态文件、/models之外的所有路径),加个/search/前缀能避免误匹配其他合法接口。 - 数据库连接泄漏:你每次查询都创建新连接,但之前没关闭它,长期运行会导致数据库连接耗尽,记得在查询回调里调用
connection.end()。 - 错误处理优化:原来的
res.send()之后又调用res.sendStatus(500)会导致响应混乱,改用res.status(500).send(...)统一设置状态码和内容,同时打印错误日志方便定位问题。 - 按ID查询接口的连接关闭:同样给按ID查询的接口补上连接关闭逻辑:
app.get('/models/:id', (req, res, next)=>{ console.log('Fetching id ' + req.params.id); const connection = getConnection(); const queryStr = 'SELECT * FROM products WHERE id=?' const modelId = req.params.id; connection.query( queryStr, [modelId], (err, rows, fields)=>{ connection.end(); // 关闭连接 if (err){ console.error('SQL查询错误:', err); res.status(500).send('<h1>500 Server Error</h1> Error! Sorry for error, we are working on it!'); return; } console.log('Ready'); res.json(rows); } ) })
4. 验证前置条件
确保你的products表的name字段已经创建了全文索引,否则MATCH AGAINST会直接报错。如果没创建,执行以下SQL:
ALTER TABLE products ADD FULLTEXT INDEX idx_product_name (name);
完成以上修改后,启动服务器访问http://localhost:3000/search/你的产品名称,控制台就能打印出正确的查询结果,客户端也能收到正常的JSON响应了。
内容的提问来源于stack exchange,提问作者user8283671
相关产品推荐
相关产品推荐

