如何在Express中执行多条MySQL插入操作后统一返回响应
Express+MySQL 批量插入完成后再返回响应的实现方案
首先你现有代码无法满足需求的核心原因和存在的问题:
- 数据库
query操作为异步回调执行,循环内的子表插入操作还未全部执行完成,外层就已经调用res.status(200).send()返回了响应 - 直接拼接用户传入的参数到SQL语句中,存在严重的SQL注入风险
- 存在多处笔误:循环中取子项参数应为
req.body.items[i].name而非req.items.name,数据库连接对象connection和con混用 - 没有事务保障,可能出现主表插入成功、子表部分插入成功的脏数据问题
推荐实现方案(带事务保障 + async/await)
该方案使用mysql2的promise API,配合事务实现要么全成功要么全回滚的原子性操作,逻辑清晰易维护:
- 首先安装mysql2依赖:
npm install mysql2 - 配置数据库连接池(性能优于单连接):
const mysql = require('mysql2/promise'); const pool = mysql.createPool({ host: '你的数据库地址', user: '数据库用户名', password: '数据库密码', database: '数据库名称', connectionLimit: 10 });
- 接口实现代码:
app.post("/api/eeee", async (req, res) => { let connection; try { // 获取连接并开启事务 connection = await pool.getConnection(); await connection.beginTransaction(); // 插入主表数据,使用预编译语句避免SQL注入 const [docResult] = await connection.execute( 'INSERT INTO documents (name) VALUES (?)', [req.body.name] ); const docId = docResult.insertId; // 组装子表批量插入参数,一次性执行批量插入(性能远高于循环单条插入) const insertParams = req.body.items.map(item => [docId, item.name]); await connection.query( 'INSERT INTO doc_items (document, name) VALUES ?', [insertParams] ); // 所有操作成功提交事务 await connection.commit(); res.status(200).json({ code: 200, msg: '插入成功' }); } catch (err) { // 任何步骤出错回滚事务,保证数据一致性 if (connection) await connection.rollback(); res.status(500).json({ code: 500, msg: '插入失败', error: err.message }); } finally { // 释放数据库连接 if (connection) connection.release(); } });
回调版本兼容实现(无需修改原有mysql依赖)
如果你不想更换现有mysql依赖的回调写法,可以用计数法判断所有插入是否完成:
app.post("/api/eeee", (req, res) => { // 预编译传参避免SQL注入 const insertDocSql = "INSERT INTO documents (name) VALUES (?)"; connection.query(insertDocSql, [req.body.name], (error, result) => { if (error) { return res.status(500).json({ msg: '主文档插入失败' }); } const docId = result.insertId; const items = req.body.items; const totalCount = items.length; let finishCount = 0; let hasError = false; for (let i = 0; i < totalCount; i++) { const insertItemSql = "INSERT INTO doc_items (document, name) VALUES (?,?)"; connection.query(insertItemSql, [docId, items[i].name], (err) => { if (err) { hasError = true; return res.status(500).json({ msg: '子项插入失败' }); } finishCount++; // 所有子项插入完成后再返回响应 if (finishCount === totalCount && !hasError) { res.status(200).json({ msg: '插入成功' }); } }); } }); });
内容的提问来源于stack exchange,提问作者Gayantha
相关产品推荐
相关产品推荐

