我有一个触发器,无论何时输入值,它都会自动将给定条目的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毫秒.
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)