症状
User-Defined Functions (在 Transact-SQL 中实现且返回单个数据值的 UDF) 称为 T-SQL 标量 User-Defined Functions (UDF) 。
标量 UDF 内联功能于 2019 Microsoft SQL Server 中引入。 此功能可以提高调用 T-SQL 标量 UDF 的查询的性能,其中 UDF 执行是主要瓶颈。 T-SQL 标量 UDF 内联自动将内联 UDF 转换为关系表达式。
对于使用标量 UDF 内联的查询可能会返回错误消息或意外结果的方案,此累积更新 (CU) 包括以下几个方面的 修补程序 :
- 如果 UDF 的返回类型是
sql_variantSQL Server 2019 CU2) 中添加的 (,则会发生类型不匹配错误。 - 来自
sp_executesql的 UDF 调用将取消执行 (SQL Server 2019 CU2) 中添加。 - 引用没有关联
GOTO命令的标签的 UDF 返回SQL Server 2019 CU2) 中添加 (不正确的结果。 - 内存不足情况和内存泄漏是由于SQL Server 2019 CU2) 中添加了非常大的标量 UDF (。
- 条件 ()
IF-ELSE语句中使用的未初始化变量会导致 (SQL Server 2019 CU2) 中添加错误。 - 如果 UDF 在
sql_variantSQL Server 2019 CU7) 中添加参数 (,则会发生显式转换错误。 - 如果标量函数引用
CHECKSUM(SQL Server 2019 CU7) 中添加,则会发生错误。 - 具有许多标量表达式重新计算的 UDF 调用可能会导致SQL Server 2019 CU7) 中添加 (无产计划程序错误。
注意:此问题的修复有时可能会导致性能下降。 若要缓解这种性能回归,可以通过打开跟踪标志 (TF) 13156 来禁用原始修复。
Microsoft正在针对将来的 CU 中提供的此性能回归进行修复。 - 如果 UDF 引用查询使用
OPTION (RECOMPILE)SQL Server 2019 CU7) 中添加 (,则会发生错误。 - 如果视图调用 (SQL Server 2019 CU9) 中添加的内联 UDF,则会发生权限错误。
- 如果使用
query_tsql_scalar_udf_inlinedXEvent (添加到 SQL Server 2019 CU9) ,则会发生访问冲突。 - 出现不一致行为的原因是标量 UDF 内联不遵循
QUERY_OPTIMIZER_COMPATIBILITY_LEVEL_nSQL Server 2019 CU9) 中添加的查询提示 (。 - 内联 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 和RETURNSQL Server 2019 CU19) 中添加的标签和语句,则会发生访问冲突。 - 当标量 UDF 内联功能处于打开状态时,标量 UDF 返回不同的日期和时间格式, (SQL Server 2022 CU3 和 SQL Server 2019 CU20) 中添加。
- 如果在
GROUP BYSQL Server 2022 CU12 (和 SQL Server 2019 CU26) 中添加了不包含聚合函数的语句中使用内联 UDFSELECT,则会生成转储文件。 - 如果启用标量 UDF 内联功能,则会出现错误“超过最大存储过程、函数、触发器或视图嵌套级别 (限制 32) ”,即使未超出嵌套级别 (添加到 SQL Server 2022 CU12 和 SQL Server 2019 CU26) 。
- 如果启用了标量 UDF 内联功能, (SQL Server 2022 CU12 和 SQL Server 2019 CU26) 中添加,则会发生
sqllang.dll!CProchdr::FDeriveInlineabilityOfScalarUdf内存损坏。 - 由于标量 UDF 内联和 (在 SQL Server 2022 CU17 和
OPTION (RECOMPILE)SQL Server 2019 CU31) 中添加的同一查询 (组合,导致结果不正确。
此累积更新还会 在 以下方案中阻止内联:
- 例如,如果 UDF 引用某些内部函数 (,
@@ROWCOUNT则) 在SQL Server 2019 CU2) 中添加内联 (,则可能会更改结果。 - 如果将聚合函数作为参数传递给标量 UDF, (SQL Server 2019 CU2) 中添加。
- 如果 UDF 引用内置视图 (例如:
OBJECT_ID) (SQL Server 2019 CU2) 中添加。 - 如果 UDF 使用 XML 方法 (SQL Server 2019 CU4 中添加) 。
- 如果 UDF 包含使用
SELECTORDER BY子句的语句,但未TOP 1(SQL Server 2019 CU4) 中添加。 - 例如,
SELECT如果语句与ORDER BY子句 (一起执行赋值,SELECT @x = @x +1 FROM table ORDER BY column_name) (SQL Server 2019 CU4) 。 - 如果 UDF 包含多个
RETURN语句 (添加到 SQL Server 2019 CU5) 。 - 如果从
RETURNSQL Server 2019 CU5) 中添加 (语句调用 UDF。 - 如果 UDF 引用 (
STRING_AGGSQL Server 2019 CU5) 中添加函数。 - 如果 UDF 定义引用 (SQL Server 2019 CU6) 中添加远程表。
- 如果 UDF 调用查询使用
GROUPING SETS、CUBE或ROLLUP(添加到 SQL Server 2019 CU6) 。 - 例如,如果 UDF 调用查询包含用作赋值 (的 UDF 参数的变量,
SELECT @y=2, @x=UDF(@y)) (添加到 SQL Server 2019 CU6) 。 - 如果 UDF 引用 (SQL Server 2019 CU11) 中添加的加密列。
- 如果 UDF 包含对
WITH XMLNAMESPACESSQL Server 2019 CU11) 中添加 (的引用。 - 如果调用 UDF 的查询在 SQL Server 2019 CU11) 中添加了通用表表达式 (CTE) (。
- 如果 UDF 定义包含临时表或临时表的同义词 (SQL Server 2022 CU1 和 SQL Server 2019 CU19) 中添加。
- 如果 UDF 定义具有语句
SELECT以及DISTINCT多个赋值列的子句, (SQL Server 2022 CU4 和 SQL Server 2019 CU20) 中添加。 - 如果 UDF 包含使用
SELECTTABLESAMPLE PERCENT子句和多个变量赋值的语句, (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的每个新累积更新都包含以前的累积更新中包含的所有修补程序和所有安全修补程序。 查看SQL Server的最新累积更新:
状态
Microsoft 已经确认在“适用范围”部分中列出的 Microsoft 产品中存在此问题。
参考资料
了解 Microsoft 用于描述软件更新的术语。