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

结果如图所示:

MS SQL更新时变量、函数、子查询及字段计算顺序探索_第1张图片

 此时发现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

此时的结果如下:

MS SQL更新时变量、函数、子查询及字段计算顺序探索_第2张图片

 此时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列的值更新为函数的值,可以看到字段的赋值在函数和子查询之前了:

MS SQL更新时变量、函数、子查询及字段计算顺序探索_第3张图片

结论 

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

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

你可能感兴趣的:(数据库,SQL与数据库资料,sql,数据库)