【问题标题】:SqlServer 2019 using table and scalar function into cursorSql Server 2019 在游标中使用表和标量函数
【发布时间】:2020-06-01 06:44:21
【问题描述】:

我发生了一个奇怪的错误:

消息 596,第 21 级,状态 1,第 0 行

无法继续执行,因为会话处于终止状态 状态。

当我使用像这样的游标时似乎会产生错误:

DECLARE dbCursor CURSOR
            FOR 
                SELECT (SELECT TOP 1 VAL FROM dbo.fn_Table('n:',dbo.[fn_Scalar](var)) ORDER BY VAL) 
                from table

如果我选择运行它,就可以了。

如果在游标中我只执行 fn_Table OR fn_Scalar,没关系。

如果在光标中我执行了这两个函数,我就会出现上述错误。

在旧版本的 SQL Server(比 2019 年)中,游标运行正常。

请给我一个想法好吗?

谢谢。

L.E. 功能是: ALTER 函数 [dbo].[UrlDecode](@url nvarchar(max)) 返回 nvarchar(max) 作为 开始 声明@foo datetime=getdate();

声明@Position INT, @Base CHAR(16), @High TINYINT, @Low TINYINT, @Pattern CHAR(21)

SELECT  @Base = '0123456789abcdef',
    @Pattern = '%[%][0-9a-f][0-9a-f]%',
    @URL = REPLACE(@URL, '+', ' '),
    @Position = PATINDEX(@Pattern, @URL)

WHILE @Position > 0
    SELECT  @High = CHARINDEX(SUBSTRING(@URL, @Position + 1, 1), @Base COLLATE Latin1_General_CI_AS),
        @Low = CHARINDEX(SUBSTRING(@URL, @Position + 2, 1), @Base COLLATE Latin1_General_CI_AS),
        @URL = STUFF(@URL, @Position, 3, CHAR(16 * @High + @Low - 17)),
        @Position = PATINDEX(@Pattern, @URL)

RETURN  @URL

结束

ALTER FUNCTION [dbo].[Split] (@sep VARCHAR(32), @s VARCHAR(MAX))

返回@t 表 ( val VARCHAR(MAX) )

作为 开始

--declare @foo datetime=getdate();
--Remove separator if the case
IF RIGHT(LTRIM(RTRIM(@s)),1) = @sep 
    SET @s = LEFT(LTRIM(RTRIM(@s)), LEN(LTRIM(RTRIM(@s))) - 1);

DECLARE @xml XML
SET @XML = N'<root><r>' + REPLACE(@s, @sep, '</r><r>') + '</r></root>'

INSERT INTO @t(val)
SELECT r.value('.','VARCHAR(250)') as Item
FROM @xml.nodes('//root/r') AS RECORDS(r)

RETURN

结束

光标是: 声明 cursor_product CURSOR 为了 select (SELECT TOP 1 VAL FROM dbo.split('n:',dbo.UrlDecode) ORDER BY VAL) from ABSENTEE

打开光标产品;

FETCH NEXT FROM cursor_product 而@@FETCH_STATUS = 0 开始

    FETCH NEXT FROM cursor_product
END;

关闭 cursor_product; DEALLOCATE cursor_product;

请忽略光标是如何定义的,无论如何都会发生错误。 谢谢。

【问题讨论】:

  • 在 fn_Scalar() 的任意位置添加 foo 语句:声明 @foo datetime=getdate();执行你的陈述。如果可行,请阅读 sql2019 中的标量 udf 内联
  • 对不起,我不明白这个建议。正如我所说,如果没有将这些函数一起用于游标,则这些函数正在工作。
  • SQL Server 错误日志中是否有相关消息,例如转储?如果是,请应用最新的 CU(如果您尚未这样做)。
  • 我有这些文件,但我对它们一无所知。我从 sql server 安装了最新的更新。
  • 你试过 lptr 建议了吗?,他告诉你在你的函数中添加一个“declare @foo datetime=getdate()”。他向你解释原因是因为添加了标量 udf 内联在 SQL Server 2019 中,并搜索有关它的更多信息。此功能是对函数执行的优化,如果添加变量声明,则会禁用此新优化,因此它将在未优化的情况下执行,因为它们在 2019 年之前在 SQL Server 上执行。

标签: sql sql-server function cursor scalar


【解决方案1】:

如果单独选择运行良好,我建议您先将数据检索到表变量中,以便稍后在对函数的调用完成后对其进行迭代,避免这些调用之间出现任何奇怪的锁定。

DECLARE @MyData table (VAL int)

INSERT INTO @MyData (VAL)
       SELECT (SELECT TOP 1 VAL FROM dbo.fn_Table('n:',dbo.[fn_Scalar](var)) ORDER BY VAL) 
       FROM table

DECLARE dbCursor CURSOR FOR SELECT VAL FROM @MyData

【讨论】:

  • 这是一个古老的功能,这种组合(2个功能到一个光标中)存在于很多地方。我需要知道是否可以更改 Sql server 选项中的某些内容以运行脚本。
  • 你可以试试@lptr 的建议。我已经为你解释了更多。
【解决方案2】:

就目前而言,您必须更改游标的选择语句(标量 udf-inlining 只是一个盲目的猜测 [function+sql2019 not working, but works pre-sql2019] ,问题是游标的执行):

选项1:

The answer of Marc Guillot (populate a table and iterate over that)

选项 2:APPLY(函数调用)

DECLARE cursor_product CURSOR FOR 
select f.VAL
from ABSENTEE as a
cross /*outer ?*/ apply
(
    SELECT TOP 1 VAL 
    FROM dbo.split('n:',dbo.UrlDecode(a.columnXYZ)) 
    ORDER BY VAL
) as f;

选项 3:在 ABSENTEE 表上聚合

DECLARE cursor_product CURSOR FOR 
select (SELECT TOP 1 VAL FROM dbo.split('n:',dbo.UrlDecode(columnXYZ)) ORDER BY VAL) 
from ABSENTEE
group by ABSENTEE.columnXYZ, ABSENTEE.othercolumn(s)

选项 4:函数结果的窗口聚合

DECLARE cursor_product CURSOR FOR 
select 
    MIN(
          (SELECT TOP 1 VAL FROM dbo.split('n:',dbo.UrlDecode(columnXYZ)) ORDER BY VAL) 
       ) over(partition by columnXYZ)
from ABSENTEE

【讨论】:

  • 我需要了解:请您告诉为什么该功能不正确?我尝试使用 CREATE FUNCTION fn_Table ( at id NVARCHAR(MAX))RETURNS TABLE AS RETURN ( SELECT at id as val) 并且光标工作
  • 功能没有问题。 SQL2019 在尝试执行游标时崩溃。检查 sql 错误日志:“SQL Server 正在终止此会话。请使用日志目录中生成的转储联系产品支持服务。”。您可能想将其报告为错误:feedback.azure.com/forums/908035-sql-server
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-14
  • 1970-01-01
  • 1970-01-01
  • 2016-08-21
  • 2021-03-14
  • 1970-01-01
相关资源
最近更新 更多