SQL Server:被GETDATE()所吸引

csh*_*hah 9 t-sql sql-server sql-server-2005

我有SQL Server 2005标准Service Pack 2 9.00.4053.00(英特尔X86)

表有近3000万行..

如果我做

SELECT GETDATE(), * FROM
<table>
Run Code Online (Sandbox Code Playgroud)

返回相同的日期和时间值,包括毫秒部分 ..虽然查询花费了超过3分钟才能完成...

我已经读过了

http://sqlblog.com/blogs/andrew_kelly/archive/2008/02/27/when-getdate-is-not-a-constant.aspx

http://social.msdn.microsoft.com/Forums/en-US/transactsql/thread/66507b8b-4a74-44c1-9637-3ab5f75db6a0

我发布的一个链接(标记答案)表明,在SQL 2005之前,GETDATE是确定性的,尽管SQL 2000 BOL声明GETDATE是不确定的

如果我用数百万行进行更新

UPDATE tableName
SET dateColumn = GETDATE()
Run Code Online (Sandbox Code Playgroud)

我知道你真的想做

DECLARE @DT datetime
SET @DT = GETDATE()
UPDATE table
SET datecol =@DT
Run Code Online (Sandbox Code Playgroud)

我真的很困惑

什么是预期的行为?

  1. 如果是我之前发布的select语句
  2. 更新语句的行为

考虑到你正在更新一个包含1亿行的表上的日期字符日期列将具有相同的日期和时间(以毫秒为单位)....

Mar*_*ith 10

GetDate()从来都不是确定性的.确定性意味着它在传递相同参数时将始终返回相同的结果.

与此相同,每列rand()评估一次,但一旦评估,对所有行保持相同.

这是比较容易看到这种行为rand()getdate()

select top 4 rand(), rand()
from sys.objects
Run Code Online (Sandbox Code Playgroud)

---------------------- ----------------------
0.0566172633850772     0.431111195699363
0.0566172633850772     0.431111195699363
0.0566172633850772     0.431111195699363
0.0566172633850772     0.431111195699363
Run Code Online (Sandbox Code Playgroud)

如果您尝试以下

select top 10 getdate(), getdate()
from sys.objects
Run Code Online (Sandbox Code Playgroud)

并查看实际执行计划中的ComputeScalar运算符属性,您将看到它GetDate()被评估两次.

注意:在SQL 2000(我不知道)之后,每列而不是每个查询的这种评估行为可能会发生变化,但这不是BOL定义为确定性的含义.


gbn*_*gbn 4

继 Martin Smith 的回答之后,所提到的决定论是 udf 行为的变化。在 SQL Server 2000 中,不能在 udf 中使用 GETDATE。您可以在 SQL Server 2005 中使用。也请参阅此链接

正如 Martin Smith 所说,某些函数是按列、每个查询进行评估的。不是每行。GETDATE 是一个,RAND 是另一个。

如果您确实需要逐行评估 GETDATE,请将其包装在 udf 中。

编辑:

NEWID 在统计上是唯一的。必须逐行对其进行评估,这样就不会在另一行中出现相同的值。因此CHECKSUM(NEWID())生成逐行随机数的技巧......