MS SQL更新时变量函数子查询及字段计算顺序探索

Posted Hello World,

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MS SQL更新时变量函数子查询及字段计算顺序探索相关的知识,希望对你有一定的参考价值。

思考

如果在更新语句中引用到变量,并且在更新语句中对变量赋值,更新后的值将如何变化?另外变量与字段的更新顺序又是怎样的呢?

探索

创建表并插入数据,声明变量,在更新语句中对变量及字段进行变更:

DECLARE @t TABLE(seq INT IDENTITY, a INT,b INT,c INT, d INT,e INT)
INSERT @t VALUES (0,0,0,0,1),(0,0,0,0,2),(0,0,0,0,3),(0,0,0,0,4),(0,0,0,0,5)
SELECT * FROM @t

DECLARE @n INT=1
UPDATE @t SET a=@n,@n=@n+1,b=@n,c=(SELECT @n),d=e,e=d
SELECT * FROM @t

结果如图所示:

 此时发现a、b两列的值是一样的,更新语句中对变量的赋值位置不会影响到更新的值,而d、e两列的内容互换了。但是采购子查询更新的c列内容全部是变量的初始值。说明子查询被优化了,只计算了一次?

通过此次示例可以看到计算的顺序是先算子查询,而且子查询中的变量不会改变,然后每行会先更新变量值,再更新字段值。

那如果子查询中要根据不同的变量值来获取不同的值怎么办呢?

根据实践,只有采用函数来处理,才会实现针对不同变更值获取不同返回内容。

先创建函数,示例中仅简单地返回原来的值:

CREATE FUNCTION GetN
(
    @N INT
)
RETURNS INT
AS
    BEGIN
        RETURN @N;
    END;
GO

然后在更新语句中调用此函数:

SET @n =1
UPDATE @t SET a=@n,@n=@n+1,b=dbo.getn(@n),c=(SELECT @n),e=b,d=e
SELECT * FROM @t

此时的结果如下:

 此时b列是通过函数调用生成的,c列仍然是子查询,可以看到b列的结果同样是在变量更新后调用的子查询值,如果将变更的赋值放到b列赋值的后面结果也是一样的。

所以顺序仍然是先变量、后函数和字段。但函数和字段赋值的顺序又是什么样子呢?

两次修改更新语句如下:

DECLARE @n INT=1
UPDATE @t SET a=dbo.getn(@n),@n=@n+1,b=dbo.getn(@n),c=(SELECT @n),e=c,d=a
SELECT * FROM @t

此次将d列的值更新为a列的值,e的值更新为c的值,a列的值更新为函数的值,可以看到字段的赋值在函数和子查询之前了:

结论 

所以优先顺序为变量>字段(所有字段同时更新)>子查询和函数。

字段同时更新其实是因为更新是有一个Deleted临时表,里面记录了原始值,所以看上去是同时更新的。

以上是关于MS SQL更新时变量函数子查询及字段计算顺序探索的主要内容,如果未能解决你的问题,请参考以下文章

MySQL进阶8 分页查询(limit) - SQL查询语法顺序及大致结构- 子查询的3个经典案例

库存 SQL 查询出现歧义错误,其中两个字段应相等以进行计算。 MS-ACCESS

SQL语句汇总——聚合函数分组子查询及组合查询

oracle sql 转换成 hive sql -子查询转关联查询(十七),子查询中有2个表外字段关联写法,round函数与power函数的运用

SQL语句汇总(三)——聚合函数分组子查询及组合查询 - Darly

基于控件名称而不是控件源(字段)的 MS Access 计算