症状
User-Defined Functions (在 Transact-SQL 中实现且返回单个数据值的 UDF) 称为 T-SQL 标量 User-Defined Functions (UDF) 。
Microsoft SQL Server 2019 中引入了标量 UDF 内联功能。 此功能可以提高调用 T-SQL 标量 UDF 的查询的性能,其中 UDF 执行是main瓶颈。 T-SQL 标量 UDF 内联自动将内联 UDF 转换为关系表达式。
对于使用标量 UDF 内联的查询可能会返回错误消息或意外结果的方案,此累积更新 (CU) 包括以下几个方面的 修补程序 :
-
如果 UDF 的返回类型是SQL Server 2019 CU2) 中添加的 sql_variant (,则会发生类型不匹配错误。
-
来自sp_executesql的 UDF 调用将取消SQL Server 2019 CU2) 中添加的执行 (。
-
引用没有关联 GOTO 命令的标签的 UDF (在 SQL Server 2019 CU2) 中添加 (返回不正确的结果。
-
内存不足情况和内存泄漏是由于SQL Server 2019 CU2) 中添加了非常大的标量 UDF (。
-
在 condition (IF-ELSE) 语句中使用的未初始化变量会导致错误 (添加到 SQL Server 2019 CU2) 。
-
如果在 SQL Server 2019 CU7) 中添加 (UDF 具有 sql_variant参数,则会发生显式转换错误。
-
如果标量函数引用 CHECKSUM(SQL Server 2019 CU7) 中添加,则会发生错误。
-
具有许多标量表达式重新计算的 UDF 调用可能会导致SQL Server 2019 CU7) 中添加 (无产计划程序错误。
注意:此问题的修复有时可能会导致性能下降。 若要缓解这种性能回归,可以通过打开跟踪标志 (TF) 13156 来禁用原始修复。
Microsoft 正在针对将来的 CU 中提供的此性能回归进行修复。
-
如果 UDF 引用查询使用 SQL Server 2019 CU7) 中添加 OPTION (RECOMPILE)(,则会发生错误。
-
如果视图调用 (SQL Server 2019 CU9) 中添加的内联 UDF,则会发生权限错误。
-
如果在 SQL Server 2019 CU9) 中使用query_tsql_scalar_udf_inlinedXEvent (添加,则会发生访问冲突。
-
出现不一致行为的原因是标量 UDF 内联不遵循SQL Server 2019 CU9) 中添加 ( QUERY_OPTIMIZER_COMPATIBILITY_LEVEL_n查询提示。
-
内联 UDF 包含可能导致无结果计划程序错误的聚合, (SQL Server 2019 CU9) 中添加。
-
出现内存不足错误的原因是, (SQL Server 2019 CU9) 中添加的条件块中的同一变量上的一系列标量操作。
-
升级到 CU9 后,如果对象调用标量内联 UDF (UDF1) 具有标量内联 UDF (UDF2) , (用作SQL Server 2019 CU11) 中添加的输入参数,则会发生访问冲突。
-
内联 UDF 可能会导致错误,并生成错误代码 6846、1011 和 107, (添加到 SQL Server 2019 CU11) 。
-
作为非 sysadmin 帐户运行的内联 UDF 可能会返回错误消息“当前命令上发生了严重错误。 结果(如果有)应丢弃“ (SQL Server 2019 CU16) 中添加。
-
如果使用 Microsoft SQL Server 2022 CU1 (和 SQL Server 2019 CU19) 中添加的同义词在 UDF 内调用临时表,则会发生访问冲突。
-
如果 UDF 定义仅包含 GOTO 标签和 (添加到 SQL Server 2022 CU1 和 SQL Server 2019 CU19) 中的RETURN 语句,则会发生访问冲突。
-
当标量 UDF 内联功能处于打开状态时,标量 UDF 返回不同的日期和时间格式, (SQL Server 2022 CU3 和 SQL Server 2019 CU20) 中添加。
-
如果具有 GROUP BY 子句的查询在 SQL Server 2022 CU12 和 SQL Server 2019 CU26) 中添加聚合函数的 (在 SELECT 语句中使用内联 UDF,则会生成转储文件。
-
如果启用标量 UDF 内联功能,则会出现错误“超过最大存储过程、函数、触发器或视图嵌套级别 (限制 32) ”,即使未超出嵌套级别 (添加到 SQL Server 2022 CU12 和 SQL Server 2019 CU26) 。
-
如果在 SQL Server 2022 CU12 (和 SQL Server 2019 CU26) 中添加标量 UDF 内联功能,则 sqllang.dll!CProchdr::FDeriveInlineabilityOfScalarUdf 会出现内存损坏。
此累积更新还会 在以下方案中阻止内联:
-
例如,如果 UDF 引用某些内部函数 (, @@ROWCOUNT) 在 2019 CU2) SQL Server 中添加内联 UDF 时 (可能会更改结果。
-
将聚合函数作为参数传递给标量 UDF 时, (SQL Server 2019 CU2) 中添加。
-
如果 UDF 引用内置视图 (例如:SQL Server 2019 CU2) 中添加 OBJECT_ID) (。
-
如果 UDF 使用 XML 方法 (SQL Server 2019 CU4 中添加) 。
-
如果 UDF 包含使用ORDER BY子句但不 TOP 1(SQL Server 2019 CU4) 中添加的 SELECT语句。
-
例如,如果SELECT 语句与 ORDER BY 子句 (一起执行赋值, SELECT @x = @x +1 FROM table ORDER BY column_name) (SQL Server 2019 CU4) 中添加。
-
如果 UDF 包含多个 RETURN 语句 (添加到 SQL Server 2019 CU5) 。
-
如果从 SQL Server 2019 CU5) 中添加的 RETURN 语句 (调用 UDF。
-
如果 UDF 引用 (SQL Server 2019 CU5) 中添加 STRING_AGG 函数。
-
如果 UDF 定义引用 (SQL Server 2019 CU6) 中添加远程表。
-
如果 UDF 调用查询使用 SQL Server 2019 CU6) 中添加的 GROUPING SETS、 CUBE或 ROLLUP (。
-
例如,如果 UDF 调用查询包含用作赋值 (的 UDF 参数的变量, SELECT @y=2, @x=UDF(@y)) (添加到 SQL Server 2019 CU6) 。
-
如果 UDF 引用 (SQL Server 2019 CU11) 中添加的加密列。
-
如果 UDF 包含对 SQL Server 2019 CU11) 中添加 WITH XMLNAMESPACES(的引用。
-
如果调用 UDF 的查询具有通用表表达式 (CTE,) (SQL Server 2019 CU11) 中添加。
-
如果 UDF 定义包含临时表或临时表的同义词 (SQL Server 2022 CU1 和 SQL Server 2019 CU19) 中添加。
-
如果 UDF 定义具有SELECT语句以及多个赋值列的DISTINCT子句 (添加到 SQL Server 2022 CU4 和 SQL Server 2019 CU20) 。
-
如果 UDF 包含使用 TABLESAMPLE PERCENT 子句和多个变量赋值的 SELECT 语句, (SQL Server 2022 CU7) 中添加。
-
如果 INSERT 查询位于包含 SQL Server 2022 CU12 和 SQL Server 2019 CU26) 中添加的 UDF (索引视图所引用的表上。
升级到 SQL Server 2019 CU2 之后,但在升级到 SQL Server 2019 CU5 之前,应重新评估 UDF 是否有资格进行内联。 为此,请通过以下方法之一刷新符合条件的标量 UDF:
-
针对适用的标量 UDF 运行 sp_refreshsqlmodule 。 有关此系统存储过程的详细信息,请参阅 sp_refreshsqlmodule (Transact-SQL)。
-
使用现有定义、权限和设置属性更改或重新创建现有标量 UDF。 有关详细信息,请参阅 ALTER FUNCTION (Transact-SQL)。
以下命令生成一个脚本来刷新任何现有内联标量 UDF 的元数据:
/*
Generates a script that can be used to refresh all active inlineable scalar UDFs.
Note The sp_refreshsqlmodule command does not affect any permissions, extended properties, or SET options that are associated with the object.
*/
SELECT 'EXECUTE sys.sp_refreshsqlmodule ''[' + OBJECT_SCHEMA_NAME(object_id) + +'].' + '[' + OBJECT_NAME(object_id)
+ ']'';' AS 'RefreshStatement'
FROM sys.sql_modules
WHERE is_inlineable = 1
AND inline_type = 1;
GO
注意:升级到 SQL Server 2019 CU5 后,我们将在编译期间恢复自动派生 UDF 内联性。
解决方法
以下SQL Server累积更新中修复了此问题:
SQL Server的每个新累积更新都包含以前的累积更新中包含的所有修补程序和所有安全修补程序。 查看SQL Server的最新累积更新:
状态
Microsoft 已经确认这是在“适用范围”部分中列出的 Microsoft 产品中存在的问题。
参考
了解 Microsoft 用于描述软件更新的术语。