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

本文详细探讨了SQL更新语句中变量与字段更新的顺序,通过示例展示了变量如何影响更新结果,子查询和函数的执行时机,以及字段更新的同步特性。实验表明,更新顺序为变量、字段(所有字段同时更新)、子查询和函数,其中函数调用发生在字段赋值之前,而子查询可能被优化只计算一次。对于依赖变量值的子查询,使用函数可以确保每次调用时获取最新值。
摘要由CSDN通过智能技术生成

思考

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

探索

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

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临时表,里面记录了原始值,所以看上去是同时更新的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hello World,

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值