Sql server 如果在同一语句中使用两次,GETUTCDATE()是否返回相同的值?
我有一个触发器,每当输入值时,它会自动将给定条目的CreationDate和ModifiedDate设置为当前UTC时间。(此后CreationDate将保持不变,而ModifiedDate将通过另一个触发器在每次更新时更新) 我想确保插入的和从未更新的项目对于CreationDate和ModifiedDate具有完全相同的值,因此我使用了如下变量:Sql server 如果在同一语句中使用两次,GETUTCDATE()是否返回相同的值?,sql-server,Sql Server,我有一个触发器,每当输入值时,它会自动将给定条目的CreationDate和ModifiedDate设置为当前UTC时间。(此后CreationDate将保持不变,而ModifiedDate将通过另一个触发器在每次更新时更新) 我想确保插入的和从未更新的项目对于CreationDate和ModifiedDate具有完全相同的值,因此我使用了如下变量: DECLARE @currentTime DATETIME SELECT @currentTime = GETUTCDATE() UPDATE d
DECLARE @currentTime DATETIME
SELECT @currentTime = GETUTCDATE()
UPDATE dbo.MyTable SET CreationDate = @currentTime, ModifiedDate = @currentTime
...
在我的命令式编程思想中,我假设这可以防止GETUTCDATE()
被调用两次,并可能产生稍微不同的结果。这真的有必要吗?如果不是,这会更贵、更便宜,还是与下面的代码完全相同
UPDATE dbo.MyTable SET CreationDate = GETUTCDATE(), ModifiedDate = GETUTCDATE()
...
它将是相同的值 GETDATE和GETUTCDATE是一些函数,每个查询只计算一次:而不是该查询中的每行或每列。优化程序将确保它们相同,因为它会同时更新值 另一个选项是定义默认约束,这样您就可以做到这一点,而不用担心它
UPDATE dbo.MyTable
SET CreationDate = DEFAULT, ModifiedDate = DEFAULT, ...
...
我有一些表具有类似的列和默认约束,从来没有出现过问题。这也意味着我永远不必考虑在代码中使用什么函数
编辑:
我可能错了:
或者我可能是对的:
第条:
Edit2:我明显错了:参见StriplingWarrior的自我回答。它是按列计算的(不是按行计算,也不是按查询计算)将GETUTCDATE()保留在变量中是一个更好的选择,因为它可以确保CreationDate和ModifiedDate保持不变。但是,我调用了每个查询的时间数,它们都返回了相同的值,因此在我看来,每个查询的GETUTCDATE()值保持不变。多亏了gbn提供的链接,我相信: 与rand()一样,它对每列计算一次,但对所有行计算一次仍然相同。 ... 查看实际执行计划中的ComputeScalar运算符属性,您将看到GetDate()计算了两次 我检查过了,在SQLServer2008中,这种情况似乎仍然以相同的方式发生:
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结束,结果显示,由于对GETUTCDATE()的第一次和第二次调用之间的所有RAND()
s的求值结果相差三毫秒.基于SQL Server 2008中的大量实验,我相信以下描述是正确的:
在单个SELECT、INSERT或UPDATE查询中,date和time函数的每个外观都将在所有行和列中显示的任何位置返回相同的值,包括列默认值
两个不同的日期和时间函数(例如GETUTCDATE()和GETDATE())可能会相互返回不同的时间(即使在调整时区或其他任何时间之后)
单个批次中的多个查询可能返回不同的值
SELECT GETUTCDATE(), GETUTCDATE() -- These will be the same
SELECT GETUTCDATE() -- These may
SELECT GETUTCDATE() -- be different
这种行为在任何地方都没有记录,使用变量可以清楚地表明意图,因此我可能不会依赖这种行为,除非避免这种依赖是一个主要负担
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.*/
为了证明这一点,在列表中选择时也会发生
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
你知道这是否是官方记录的吗?我不想依赖这种行为,除非它是一个记录在案的功能,而且我在过去也没有成功地找到这样的东西。@Jeffrey L Whitledge:它在很多地方间接记录了每个查询的函数求值,而不是每行的函数求值。包括这里等等。我会检查一下的。+1,谢谢你的链接。你说得对,它不是按行计算的,但从我收集的数据来看,它似乎是按列计算一次,但它发生得太快了,可能99.99%的时间都是相同的。@StriplingWarrior-如果99.99%的时间都是相同的,并且你的逻辑取决于列是相同的,如果您的表中有一百万行,那么您将有100行错误!也许最好还是坚持使用一个变量。@Jeffrey L Whitledge:同意。这就是为什么我给了a+1,但没有把这个答案标记为正确。谢谢你花时间来测试这个,但这实际上是不正确的。见我的最新答案。同意。执行我答案中的代码也清楚地表明了这一点。这是一个非常简单的证明,它并不总是返回相同的值。
CREATE FUNCTION dbo.GETUTCDATE()
RETURNS DATETIME
WITH SCHEMABINDING
AS
BEGIN
RETURN GETUTCDATE()
END
GO
SELECT GETUTCDATE(),dbo.GETUTCDATE()
FROM master..spt_values