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

NodeJS使用TediousJS循环执行SQL插入请求报错如何解决

解决方案

报错根因

当前代码使用同步for循环生成所有请求并立即调用connection.execSql(),不符合Tedious单连接同一时间仅能执行一个请求的限制:第一个请求发出后连接尚未回到LoggedIn状态,仍停留在等待响应的SentLogin7WithStandardLogin状态,第二个请求就已触发状态校验失败报错。

最优实现方案:批量插入

优先使用Tedious内置的BulkLoad接口完成批量插入,仅需发起一次数据库请求,性能远高于逐条插入,完全规避串行执行的复杂度。
代码示例:

const { TYPES } = require('tedious')

wb.xlsx.readFile(filePath).then(async function() {
    const sh = wb.getWorksheet('Sheet Name');
    // 第一步:遍历Excel收集所有待插入数据
    const insertRows = [];
    for (let i = 11; i <= sh.rowCount; i++) {
        const currentRow = sh.getRow(i);
        for (let j = 1; j <= currentRow.cellCount; j++) {
            if (sh.getRow(10).getCell(j).value === 'X') {
                // 按实际业务提取对应字段值
                insertRows.push({
                    column1: currentRow.getCell(1).value,
                    column2: currentRow.getCell(2).value,
                    // 其他字段按需补充
                })
            }
        }
    }

    // 第二步:初始化批量插入实例
    const bulkLoad = connection.newBulkLoad('目标表名', function (err, rowCount) {
        if (err) throw err;
        console.log(`插入完成,共影响行数:', rowCount);
        // 后续业务逻辑
    });

    // 第三步:添加表字段定义,类型需与数据库表结构匹配
    bulkLoad.addColumn('column1', TYPES.NVarChar, { nullable: false, length: 255 });
    bulkLoad.addColumn('column2', TYPES.Int, { nullable: true });
    // 其他字段按需补充

    // 第四步:批量插入数据
    insertRows.forEach(row => bulkLoad.addRow(row));
    connection.execBulkLoad(bulkLoad);
})

备选方案:异步串行逐条插入

如果业务要求必须逐条执行SQL,可以将请求封装为Promise后使用async/await串行执行:

  1. 封装异步执行方法:
function execSqlAsync(connection, query) {
    return new Promise((resolve, reject) => {
        const request = new Request(query, (err) => {
            if (err) return reject(err);
            resolve();
        })
        connection.execSql(request);
    })
}
  1. 串行执行所有请求:
wb.xlsx.readFile(filePath).then(async function() {
    const sh = wb.getWorksheet('Sheet Name');
    // 收集所有待执行SQL
    const queries = [];
    for (let i = 11; i <= sh.rowCount; i++) {
        const currentRow = sh.getRow(i);
        for (let j = 1; j <= currentRow.cellCount; j++) {
            if (sh.getRow(10).getCell(j).value === 'X') {
                const query = `INSERT INTO ...`; // 按业务拼接SQL
                queries.push(query);
            }
        }
    }

    // 串行执行
    for (const query of queries) {
        try {
            await execSqlAsync(connection, query);
        } catch (err) {
            console.error('SQL执行失败:', query, err);
            // 按业务需要选择跳过或终止执行
        }
    }
})

注意事项

  • 必须等待连接完全进入LoggedIn状态后再发起所有请求,避免连接建立过程中发起请求触发状态错误
  • 数据量较大时优先使用批量插入方案,性能比逐条插入提升10倍以上
  • 多并发场景可搭配连接池使用,从连接池获取空闲连接执行请求,无需串行等待

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 04:54:02