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串行执行:
- 封装异步执行方法:
function execSqlAsync(connection, query) { return new Promise((resolve, reject) => { const request = new Request(query, (err) => { if (err) return reject(err); resolve(); }) connection.execSql(request); }) }
- 串行执行所有请求:
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
相关产品推荐
相关产品推荐

