如果在同一语句中使用两次,GETUTCDATE()是否会返回相同的值?

Str*_*ior 13 sql-server

我有一个触发器,无论何时输入值,它都会自动将给定条目的CreationDate和ModifiedDate设置为当前UTC时间.(之后CreationDate将保持不变,而ModifiedDate将通过另一个触发器在每次更新时更新).

我想确保插入且永不更新的项目对于CreationDate和ModifiedDate具有完全相同的值,所以我使用了这样的变量:

DECLARE @currentTime DATETIME
SELECT @currentTime = GETUTCDATE()
UPDATE dbo.MyTable SET CreationDate = @currentTime, ModifiedDate = @currentTime
    ...
Run Code Online (Sandbox Code Playgroud)

在我的命令式编程心态中,我假设这可以防止GETUTCDATE()被调用两次,并可能产生稍微不同的结果.这实际上是必要的吗?如果没有,这将是更昂贵,更便宜,或与以下代码完全相同?

UPDATE dbo.MyTable SET CreationDate = GETUTCDATE(), ModifiedDate = GETUTCDATE()
    ...
Run Code Online (Sandbox Code Playgroud)

Str*_*ior 10

感谢gbn提供的链接,我相信这回答了我的问题:

与rand()一样,每列评估一次,但一旦评估,对所有行保持相同....查看实际执行计划中的ComputeScalar运算符属性,您将看到GetDate()被计算两次.

我检查过,看起来这仍然在SQL Server 2008中以相同的方式发生:GetUtcDate()在执行计划中被评估两次.它不会在每行产生不同的结果,但如果时间恰好正确,它可能会产生每列不同的结果.

编辑

我实际上可以证明这种行为!试试这个:

select GETUTCDATE(), RAND(), RAND(), ...[~3000 RAND()s]..., RAND(), GETUTCDATE()
from [TableOfYourChoice]
Run Code Online (Sandbox Code Playgroud)

在我的实验中,我最终2011-05-17 20:47:34.247在第一列和2011-05-17 20:47:34.250最后一列中显示了由于评估RAND()第一次和第二次调用GETUTCDATE()之间的所有s 而产生的差异为3毫秒.


Mar*_*ith 9

DECLARE @Counter INT = 1

WHILE (1 = (SELECT 1 WHERE GETUTCDATE()  = GETUTCDATE()))
SET @Counter = @Counter+1

SELECT @Counter /*Returns almost immediately with a number in the 000s for me.*/
Run Code Online (Sandbox Code Playgroud)

并且只是为了证明这在SELECT列表中也会发生.

DECLARE @T TABLE 
(
rownum INT IDENTITY(1,1) PRIMARY KEY,
d1 datetime,
d2 datetime
)

WHILE (NOT EXISTS(SELECT * FROM @T WHERE d1 <> d2))
    BEGIN
    DELETE FROM @T
    INSERT INTO @T 
    SELECT GETUTCDATE(),GETUTCDATE()
    END

SELECT * FROM @T
Run Code Online (Sandbox Code Playgroud)

顺便说一句:如果出于某种原因,你想GETUTCDATE()在每行的基础上进行评估,你可以将其包装在标量UDF中.

CREATE FUNCTION dbo.GETUTCDATE()
RETURNS DATETIME
WITH SCHEMABINDING
AS
BEGIN
RETURN GETUTCDATE()
END
GO

SELECT GETUTCDATE(),dbo.GETUTCDATE()
FROM master..spt_values
Run Code Online (Sandbox Code Playgroud)