由于 SQL Server 2019 Linux 中的错误,需要 node-mssql GET 请求中的解决方法两语句查询(DECLARE;SELECT)

Posted

技术标签:

【中文标题】由于 SQL Server 2019 Linux 中的错误,需要 node-mssql GET 请求中的解决方法两语句查询(DECLARE;SELECT)【英文标题】:Workaround two-statement query (DECLARE; SELECT) in node-mssql GET request required due to bug in SQL Server 2019 Linux 【发布时间】:2021-11-19 17:02:11 【问题描述】:

由于 SQL Server 2019 Linux 中的一个错误,一个 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;

在修复之前,我发现的解决方法是在查询中使用两个语句:

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

正如您在下面的 dbfiddle 中看到的,双语句查询在第二次执行时不会导致 SQL Server 2019 Linux 崩溃,而单语句查询在第二次执行时会导致 SQL Server 2019 Linux 崩溃:

https://dbfiddle.uk?rdbms=sqlserver_2019l&fiddle=4a7759a742f361fc075f35ae6fbdc186

那么,是否可以在 node-mssql GET 请求中使用两个语句(DECLARE 和 SELECT),或者我需要将查询放在存储过程中吗?如果我把它放在一个存储过程中,我可以使用 node-mssql GET 请求来执行一个存储过程并取回值吗?我正在返回一个包含一个或多个结果的 result.recordset。

编辑:

非常感谢@David 给出的答案。这似乎适用于 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 查询中使用多个语句。 不过,稍后,当我想将其推送到生产环境时,我很可能会想要使用准备好的语句。按照我的理解,分号在准备好的语句中是禁止使用的。是否可以(安全地)使用准备好的语句使用多个语句进行查询,而不必使用存储过程? (很抱歉提出其他问题,只是想确保该变通办法也适用于准备好的语句,希望这个 SQL Server 2019 Linux 错误很快得到修复。

【问题讨论】:

这在 Windows 上也失败了。被举报了吗? @DavidBrowne-Microsoft 我只在 SQL Server 2019 Linux 中看到过这个错误,而在其他任何地方都没有。我已经在 SQL Server 2019 和 2017 Windows 下对其进行了测试,它没有崩溃。我想将此报告为错误,但不愿意为 Microsoft 支持请求支付 500 美元。所以,我在这里报告了它feedback.azure.com/d365community/idea/… 和这里docs.microsoft.com/en-us/answers/questions/632037/… 不确定这些是否是报告错误的正确地方。 @DavidBrowne-Microsoft 我在这里也报告了这个错误feedback.azure.com/d365community/idea/… 【参考方案1】:

应该可以正常工作。客户并不真正知道批处理是否包含多个语句。在一般情况下,您可能需要在批处理顶部添加 SET NOCOUNT ON 以禁止向客户端发送每个语句的行数。

【讨论】:

以上是关于由于 SQL Server 2019 Linux 中的错误,需要 node-mssql GET 请求中的解决方法两语句查询(DECLARE;SELECT)的主要内容,如果未能解决你的问题,请参考以下文章

由于登录失败错误,无法连接到 SQL Server 数据库 [重复]

SQL Server on Red Hat Enterprise Linux——RHEL上的SQL Server(全截图)

SQL Server使用手册

SQL Server on Red Hat Enterprise Linux

Sql Server Linux(Redhat) Distributed Availability Group Setup — step by step

Connect SQL Server from Linux Client using Windows Authentication and troubleshoot steps