You need to enable JavaScript to run this app. Node.js Express 基于mssql跨库查询合并结果集同响应返回实现
优惠活动
大模型
产品
解决方案
定价
更多

Node.js Express 基于mssql跨库查询合并结果集同响应返回实现

原代码运行异常的核心原因
  • 接口路由内的代码是同步执行逻辑,res.send()会在两个SQL查询的异步回调还没触发、结果还没返回的时候就立刻执行,这时候两个结果集都还没被保存,返回的内容自然是空的
  • 直接调用全局mssql模块的connect、close方法,两个连续执行的数据库连接会共享同一个全局单例实例:第一次连接还在建立/查询执行的异步过程中,第二次connect就会覆盖全局的连接状态;等第一个查询执行完触发的sql.close(),会直接把刚建立的第二个连接强制关闭,导致第二个查询的回调还没拿到结果就被中断,最终出现第二个结果集始终为空的问题
  • 所有数据库操作的错误仅打印在控制台,没有中断整个执行流程,接口会在出错的情况下依然返回空内容,没有明确的错误提示
代码调整方案

核心思路是:拆分独立的数据库连接资源,把异步查询过程用Promise封装,等两个查询全部执行完成后,再统一合并结果返回。
具体调整点:

  • 针对每个独立的数据库配置,单独创建ConnectionPool连接实例,不使用全局单例共享连接资源,从根源上避免两个连接互相被关闭、状态被覆盖的问题
  • 把单库的查询逻辑封装为返回Promise的异步函数,替代原来的回调嵌套写法,方便并行等待两个查询的结果
  • 路由内用async/await等待两个查询的全部结果,确保res.send()不会提前执行
  • 增加完整的错误捕获:只要任意一步连接、查询出现异常,就及时返回500状态和明确的错误信息,避免静默失败
  • 所有数据库连接在查询完成/出错后自动释放,不要在全局层面提前调用close方法中断执行流程
调整后的可运行参考代码
const express = require('express')
const app = express()
const cors = require('cors')
const sql = require('mssql')
app.use(cors())

const config_03 = {
    server: 'server01',
    // 原有数据库配置项保留
}
const config_01 = {
    server: 'server01',
    // 原有数据库配置项保留
}

/**
 * 执行单库查询的封装函数
 * @param {object} dbConfig 对应数据库的连接配置
 * @param {string} queryStr 要执行的SQL语句
 * @returns {Promise<Array>} 查询返回的记录集
 */
async function querySingleDb(dbConfig, queryStr) {
    // 每个查询使用独立的连接池,不与其他连接共享状态
    const pool = await new sql.ConnectionPool(dbConfig).connect()
    try {
        const queryResult = await pool.request().query(queryStr)
        return queryResult.recordset
    } finally {
        // 无论查询成功或失败,用完即释放连接
        pool.close()
    }
}

app.get('/api/', async (req, res) => {
    try {
        // 并行执行两个独立查询,等待全部结果返回
        const [db03Result, db01Result] = await Promise.all([
            querySingleDb(config_03, "select foo, bar from foobar"),
            querySingleDb(config_01, "select foo, bar from foobar")
        ])

        // 合并两个结果集后统一返回
        const mergedResponse = {
            dataFrom03: db03Result,
            dataFrom01: db01Result
        }

        res.send(mergedResponse)
    } catch (err) {
        // 任意环节出错则返回明确错误
        res.status(500).send({
            message: '数据库查询执行失败',
            errorDetail: err.message
        })
    }
})

const webserver = app.listen(5000, () => {
    console.log('node running')
})
调整后的效果
  • 从根源上解决第二个查询结果为空的问题:两个连接池完全独立,不会被全局的close操作互相影响,查询流程不会被中途中断
  • 不会再出现res.send()提前执行的问题:接口会严格等待两个查询全部完成后,才把合并后的结果返回给请求方
  • 两个查询并行执行,相比串行执行总响应耗时更短
  • 完整的错误捕获机制,避免无提示的空返回问题,前端可以明确感知到查询执行异常

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.23 09:06:01