Hei*_*nzi 34 sql-server functions sql-server-2019
[更新:此问题描述了SQL Server 2019 累积更新 5 中已修复的错误。]
考虑以下重现示例(fiddle):
CREATE FUNCTION dbo.Repro (@myYear int)
RETURNS datetime
AS
BEGIN
IF @myYear <> 1990
BEGIN
RETURN NULL
END
DECLARE @firstOfYear datetime;
SET @firstOfYear = DATEFROMPARTS(@myYear, 1, 1);
IF DATEDIFF(day, @firstOfYear, @firstOfYear) <> 0
BEGIN
RETURN NULL
END
RETURN @firstOfYear
END
SELECT dbo.Repro(0);
Run Code Online (Sandbox Code Playgroud)
显然,如果输入是 ,该函数应该返回 1990 年 1 月的第一天1990,NULL否则返回。是的,我知道这DATEDIFF(day, @firstOfYear, @firstOfYear) <> 0是一个荒谬的操作。这是一个演示潜在错误的mcve,而不是生产代码。
现在让我们SELECT dbo.Repro(0)在 SQL Server 2017 和 SQL Server 2019 上执行。
预期结果:NULL。
SQL Server 2017 的实际结果:NULL
SQL Server 2019 的实际结果:
消息 289 级别 16 状态 1 第 1 行
无法构造数据类型日期,某些参数的值无效。
显然,SQL Server 2019IF @myYear <> 1990即使不应该执行初始保护子句 ( )下的一些代码。
我的问题:
Mar*_*ith 42
这是标量 UDF 内联的错误(或者可能是查询优化器的错误,标量 UDF 内联更多地暴露了该错误)。您可以使用WITH INLINE = OFF关闭该函数的内联。
使用变量而不是常量显示更多细节
declare @myYear int = 0
SELECT dbo.Repro(@myYear);
Run Code Online (Sandbox Code Playgroud)
Expr1000 = CASE WHEN [@myYear]<>(1990) THEN (1) ELSE (0) END[Expr1003] = Scalar Operator(CONVERT_IMPLICIT(datetime,datefromparts([@myYear],(1),(1)),0))当分别使用文字0to1和时,这些表达式得到了简化CONVERT_IMPLICIT(datetime,datefromparts((0),(1),(1)),0)。
在datefromparts(0计算时将抛出错误。
Expr1002 = CASE WHEN [Expr1000] = (1) THEN (1) ELSE (0) END并且Expr1002用作嵌套循环连接(节点 3)上的传递谓词。在嵌套循环内部,常量扫描(节点 7)不返回任何列。
因此,这看起来与此处的答案相同,其中受 passthru 谓词保护的嵌套循环内部的表达式被移出到未受保护的区域中。
| 归档时间: |
|
| 查看次数: |
2368 次 |
| 最近记录: |