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

时间:2011-05-17 19:43:07

标签: sql-server

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

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

DECLARE @currentTime DATETIME
SELECT @currentTime = GETUTCDATE()
UPDATE dbo.MyTable SET CreationDate = @currentTime, ModifiedDate = @currentTime
    ...

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

UPDATE dbo.MyTable SET CreationDate = GETUTCDATE(), ModifiedDate = GETUTCDATE()
    ...

5 个答案:

答案 0 :(得分:9)

感谢gbn提供的链接,我相信this answers my question

  

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

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

修改

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

select GETUTCDATE(), RAND(), RAND(), ...[~3000 RAND()s]..., RAND(), GETUTCDATE()
from [TableOfYourChoice]

在我的实验中,我在第一列中找到2011-05-17 20:47:34.247,在最后一列找到2011-05-17 20:47:34.250,显示所有{{1}的评估结果相差3毫秒在第一次和第二次调用GETUTCDATE()之间。

答案 1 :(得分: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.*/

只是为了证明在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

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

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

SELECT GETUTCDATE(),dbo.GETUTCDATE()
FROM master..spt_values

答案 2 :(得分:3)

它将是相同的值。

GETDATE和GETUTCDATE是每个查询评估一次的一些函数:不是该查询中的每行或每列。优化器将确保它们是相同的,因为它同时更新值

另一个选择是定义一个DEFAULT约束,这样你就可以做到这一点而不用担心它。

UPDATE dbo.MyTable
SET CreationDate = DEFAULT, ModifiedDate = DEFAULT, ...
...

我的表格与DEFAULT约束的列相似,从来没有问题。这也意味着我永远不必考虑我在代码中使用的功能。

编辑:

我错了:SQL Server: intrigued by GETDATE()

或者我可能是对的:Selecting GETDATE() function twice in a select list-- same value for both?

文章:Conor Cunnigham mentions it the behaviour

Edit2:我明显错了:看看StriplingWarrior的自我回答。它的每列评估 (不是每行而不是每个查询)

答案 3 :(得分:1)

将GETUTCDATE()保存在变量中是一个更好的选择,因为它可以确保CreationDate和ModifiedDate保持相同。但是,我在每个查询中调用GETUTCDATE()个时间并且它们都返回了相同的值,因此对我来说,每个查询的GETUTCDATE()值似乎保持不变。

答案 4 :(得分:-1)

基于SQL Server 2008中的大量实验,我认为以下特征是正确的:

在单个SELECT,INSERT或UPDATE查询中,日期和时间函数的每个外观将在所有行和列中显示的任何位置返回相同的值,包括列默认值。

两个不同的日期和时间函数(例如,GETUTCDATE()和GETDATE())可能会彼此返回不同的时间(即使在调整时区或其他任何内容之后)。

单个批次中的多个查询可能会返回不同的值。

SELECT GETUTCDATE(), GETUTCDATE() -- These will be the same

SELECT GETUTCDATE()  --  These may
SELECT GETUTCDATE()  --  be different

此行为未在任何地方记录,并且变量的使用使意图明确,因此我可能不会依赖此行为,除非避免这种依赖是一个主要负担。