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

Node.js for循环中执行MySQL查询 外部count统计值为0问题求助

问题根因
  • 核心是Node.js异步IO的执行逻辑:connection.query属于异步非阻塞方法,调用后不会等待数据库返回结果就会立刻执行后续代码。同步执行的for循环会瞬间把所有查询请求发出去,紧接着就执行了循环外的console.log(counts),此时所有查询的回调函数都还没有被触发,counts还是初始值0,所以始终打印0。
  • 潜在风险:原代码直接拼接SQL字符串,存在SQL注入漏洞,必须改用参数化查询。
  • 额外隐藏坑:原循环用var声明迭代变量i,如果回调中用到i会出现变量提升导致的取值错误,建议改用let或者for...of遍历。
修复方案

方案1:单次查询优化(推荐,性能最优)

不需要循环发起多次数据库请求,直接用IN条件一次查询所有存在的序列号,再对比原数组统计不存在的数量,性能远高于循环查询:

// 建议使用mysql2/promise库以支持async/await语法
const mysql = require('mysql2/promise');
// 推荐使用连接池代替单连接,性能和稳定性更好
const pool = mysql.createPool({
  host: '你的数据库地址',
  user: '数据库用户名',
  password: '数据库密码',
  database: '数据库名'
});

app.get('/stock_outward', async function (req, res) {
  try {
    const serial_values = "SV-K8B22490,SV-K8B22491,SV-K8B22492,SV-K8B22493,SV-K8B22494,SV-K8B22495,SV-K8B22496,SV-K8B22497,SV-K8B22498,SV-K8B22499";
    const serial_arys = serial_values.split(",");
    // 一次查询拿到所有存在的序列号
    const [existsResults] = await pool.query('SELECT s_no FROM stock_inward WHERE s_no IN (?)', [serial_arys]);
    // 提取存在的序列号列表
    const existsSerials = existsResults.map(item => item.s_no);
    // 过滤出不存在的序列号,统计数量
    const notExistsSerials = serial_arys.filter(serial => !existsSerials.includes(serial));
    const notExistsCount = notExistsSerials.length;

    console.log('不存在的序列号数量:', notExistsCount);
    // 返回响应给前端
    res.json({
      notExistsCount: notExistsCount,
      notExistsList: notExistsSerials
    });
  } catch (error) {
    console.error('查询失败:', error);
    res.status(500).json({ error: '服务器内部错误' });
  }
});

方案2:async/await 循环查询(适合需要单独处理每个序列号查询结果的场景)

如果确实需要逐个处理每个序列号的查询逻辑,可以用async/await保证所有查询执行完成后再统计结果:

const mysql = require('mysql2/promise');
const pool = mysql.createPool({
  // 连接配置同方案1
});

app.get('/stock_outward', async function (req, res) {
  try {
    const serial_values = "SV-K8B22490,SV-K8B22491,SV-K8B22492,SV-K8B22493,SV-K8B22494,SV-K8B22495,SV-K8B22496,SV-K8B22497,SV-K8B22498,SV-K8B22499";
    const serial_arys = serial_values.split(",");
    let existsCount = 0;

    for (const serial of serial_arys) {
      // 等待当前查询执行完成再进入下一次循环
      const [results] = await pool.query('SELECT * FROM stock_inward WHERE s_no = ?', [serial]);
      if (results.length > 0) {
        existsCount++;
      }
    }

    // 所有查询完成后统计不存在的数量
    const notExistsCount = serial_arys.length - existsCount;
    console.log('不存在的序列号数量:', notExistsCount);
    res.json({ notExistsCount: notExistsCount });
  } catch (error) {
    console.error('查询失败:', error);
    res.status(500).json({ error: '服务器内部错误' });
  }
});

方案3:回调写法兼容(无需改造为async/await)

如果要保留原回调写法,需要增加计数器判断所有查询是否全部执行完成:

app.get('/stock_outward', function (req, res) {
  const serial_values = "SV-K8B22490,SV-K8B22491,SV-K8B22492,SV-K8B22493,SV-K8B22494,SV-K8B22495,SV-K8B22496,SV-K8B22497,SV-K8B22498,SV-K8B22499";
  const serial_arys = serial_values.split(",");
  const total = serial_arys.length;
  let existsCount = 0;
  let doneCount = 0; // 记录已完成的查询数

  for (let i = 0; i < total; i++) {
    // 参数化查询避免注入
    connection.query('SELECT * FROM stock_inward WHERE s_no = ?', [serial_arys[i]], function (error, results, fields) {
      doneCount++;
      if (error) throw error;
      if (results.length > 0) {
        existsCount++;
      }
      // 所有查询都执行完成后再统计结果
      if (doneCount === total) {
        const notExistsCount = total - existsCount;
        console.log('不存在的序列号数量:', notExistsCount);
        res.json({ notExistsCount: notExistsCount });
      }
    });
  }
});

内容的提问来源于stack exchange,提问作者Kalaiarasan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 12:54:08