在标量函数中为变量赋值的逻辑

Tho*_* D. 1 sql-server optimization subquery functions

我目前正在更新旧的标量值函数,希望能够提高它们的效率或将它们更改为内联 TVF。

在对我的重写进行故障排除时,我在原始代码中遇到了一些奇怪的问题,根据我对 SQL 中变量的理解,这似乎没有意义

如果我要写

 Declare @var as Integer
 Select @var = col1 from table
Run Code Online (Sandbox Code Playgroud)

然后这将始终返回 col1 中的最后一项。但是,在我正在使用的功能中,情况似乎并非如此。最初,有一个 where 子句根据输入更改结果,但是,删除它后,上述属性应该保持不变。在大多数情况下,确实如此,但也有一些情况并非如此。

大纲大致类似于以下内容:

create function f (
@var1 ... )
returns datatype
begin
    Declare @temp1 ... (several vars declared here)
    select @temp1 = col1, @temp2 = col2, ..., @tempX = max(colX) from(
        select col1, col2, ... ,
        colX * (case when name = 'X' then 1 else 0)
        from table1 
        INNER JOIN table2 on ...
        inner join table3 on ...
        left join table4 on ...
        where x) as sq
    group by ...
    return ...
end)
Run Code Online (Sandbox Code Playgroud)

虽然比上面的基本示例更复杂,删除 where 子句后,它似乎在逻辑上应该是等效的,但是,如果我运行该函数并查看它实际返回的内容,它并不总是相同的值。请注意,出于测试目的,该函数仅返回通过 select 分配的变量之一。假设与上面给出的简单情况类似的功能,应该始终返回相同的值。

作为参数传入的值不应影响此特定语句(这是整个函数的子集,但我创建了一个较小的函数来测试这部分代码并决定保留传入的相同值以保持一致性清酒)。只使用新声明的变量并给定值;排除我在测试期间注释掉的 where 子句。

然后,我的问题是,如果连接始终相同并且没有 where 子句来更改连接中的值,这些表将如何更改以更改最后一个元素?分组也应该是一致的,因为每次运行函数时所有的表都应该是相同的。

子查询应始终返回相同的表,然后应为变量分配其特定列中的最后一个值,这意味着函数的返回值应始终为相同的值。

Han*_*non 5

然后这将始终返回 col1 中的最后一项。

“最后一项”是什么意思?在 SQL Server 中,实际上大多数(如果不是全部)RDBMS 中,没有“最后”的概念,除非您指定一个ORDER BY子句。

如果计划由于参数嗅探、更新的统计信息、新的或修改的索引等而发生变化,结果的明显顺序可能会发生巨大变化。

从不1依赖于没有明确的观察到的顺序行为ORDER BY

这个问题和随附的答案也使有关该主题的阅读变得有趣。


是的,我只是说从不。此实例是“永不言败”规则的一个例外。