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

SQL Server 2019 Linux查询崩溃问题的node-mssql适配方案咨询

SQL Server 2019 Linux geometry函数调用崩溃问题及node-mssql使用咨询

由于SQL Server 2019 Linux存在bug,原本应为单语句的node-mssql GET查询:

router.get('/getresult/:srid/:x/:y', function (req, res) {
    sql.connect(config, error => {
        new sql.Request()
            .input('srid', sql.Int, req.params.srid)
            .input('x', sql.Float, req.params.x)
            .input('y', sql.Float, req.params.y)
            .query('SELECT * from dbo.bTest(geometry::Point(@x,@y,@srid))', (error, result) => {
                         res.send(result.recordset);
                    })
            if (error) {
                console.error(`error: ${error.message}`);
            }
    })
});

现在需要拆分为两条语句执行。会导致SQL Server 2019 Linux崩溃的查询语句为:

SELECT * from dbo.bTest(geometry::Point(@x,@y,@srid))

测试用到的表值函数定义如下:

create function dbo.bTest ( @p_geom geometry )
Returns @geometries TABLE
(
  id integer,
  geom geometry
)
as
begin
  declare @g geometry;
  set @g = @p_geom.STBuffer(0.5);      
  insert into @geometries values (1, @g);
return;
end;

在官方修复该bug前,找到的临时解决方案是将查询拆分为两条语句:

DECLARE @wkt geometry = geometry::Point(@x,@y,@srid);
SELECT * FROM dbo.bTest(@wkt);

测试结果可验证,拆分后的双语句查询第二次执行时不会导致SQL Server 2019 Linux崩溃,而单语句查询第二次执行就会触发崩溃。
想咨询两个问题:

  1. node-mssql的GET请求中是否支持执行DECLARE和SELECT两条语句,还是必须将查询封装为存储过程?
  2. 如果使用存储过程,能否通过node-mssql GET请求调用存储过程并获取返回结果?需要获取的result.recordset可能包含1条或多条记录。

补充更新

已验证以下查询语句在node-mssql GET请求中可正常运行:

SET NOCOUNT ON;
DECLARE @geom geometry = geometry::Point(@x,@y,@srid);
SELECT * FROM dbo.bTest(@geom);

该方案可连续多次执行,不会触发SQL Server 2019 Linux崩溃。调整后的node-mssql router.get代码如下:

router.get('/getresult/:srid/:x/:y', function (req, res) {
    sql.connect(config, error => {
        new sql.Request()
            .input('srid', sql.Int, req.params.srid)
            .input('x', sql.Float, req.params.x)
            .input('y', sql.Float, req.params.y)
            .query('SET NOCOUNT ON; \
                DECLARE @geom geometry = geometry::Point(@x,@y,@srid)); \
                SELECT * from dbo.bTest(@geom);', (error, result) => {
                         res.send(result.recordset);
                    })
            if (error) {
                console.error(`error: ${error.message}`);
            }
    })
});

之前不知道node-mssql的查询支持多语句执行。但后续上线生产环境时需要使用预编译语句,据了解预编译语句不允许使用分号,请问是否可以不借助存储过程,安全地在预编译语句中执行多语句查询?希望确认该临时方案也能适配预编译语句的场景。


问题解答

  • 第一个问题:node-mssql原生支持多语句执行,无需强制封装为存储过程。默认配置下直接在query方法中传入用分号分隔的多语句即可正常运行,你验证过的新增SET NOCOUNT ON的写法是正确的,该参数可以避免SQL Server返回的行计数信息干扰结果集解析,确保你能直接拿到预期的recordset数据。
  • 第二个问题:存储过程完全可以通过node-mssql调用并获取返回的表结果。你可以通过request.execute('存储过程名', callback)的方式调用,输入参数和普通查询一样用input方法绑定,返回的结果结构和普通query调用完全一致,单结果集直接取recordset即可,多结果集可以通过recordsets数组获取,完全适配你需要返回1条或多条记录的需求。
  • 预编译语句补充问题:你提到的「预编译语句不允许使用分号」是误解,node-mssql的预编译(通过prepare方法实现)完全支持多语句:
    1. 预编译的语法限制仅针对参数绑定规则,并不禁止分号分隔多语句,你可以把整段SET NOCOUNT ON; DECLARE @geom ...; SELECT ...作为预编译的SQL文本直接传入
    2. 生产环境下的参考写法如下(注意修正了你原有代码中多余的右括号笔误):
    // 建议优先使用连接池避免频繁创建连接
    const pool = await sql.connect(config)
    router.get('/getresult/:srid/:x/:y', async function (req, res) {
      try {
        const ps = new sql.PreparedStatement(pool)
        ps.input('srid', sql.Int)
        ps.input('x', sql.Float)
        ps.input('y', sql.Float)
        // 预编译多语句SQL
        await ps.prepare(`
          SET NOCOUNT ON; 
          DECLARE @geom geometry = geometry::Point(@x,@y,@srid); 
          SELECT * from dbo.bTest(@geom);
        `)
        const result = await ps.execute({
          srid: req.params.srid,
          x: req.params.x,
          y: req.params.y
        })
        res.send(result.recordset)
        // 执行完成后卸载预编译语句
        await ps.unprepare()
      } catch (error) {
        console.error(`error: ${error.message}`)
        res.status(500).send(error.message)
      }
    })
    
    1. 该写法完全符合预编译的安全要求,可以规避SQL注入风险,不需要额外封装存储过程,可作为官方修复bug前的生产可用临时方案。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 19:06:02