在 SQL Server 中,存在隐式转换数据类型的规则。
在此文档页面上有一个关于可以进行哪些转换的表格。
在此文档页面上,我们可以看到什么被转换成什么。
当我隐式将整数转换为日期时间时,隐式假定的间隔为 1 天。因此,明天同一时间返回以下内容:
select getdate() + 1
然而,有人可能会认为 1 应该是一小时或一分钟。我试图在文档中找到指定隐式转换为日期时间的间隔始终为 24 小时的位置。在日期时间文档的开头,它说:
定义与基于 24 小时制的带小数秒的时间相结合的日期。
但我认为这不够精确和清晰,不足以让某人相信如果隐式转换,整数 1 将不变地表示 1 天。
那么微软有没有一个地方明确说明这一点呢?
回答您的问题“Int 1 是否总是隐式转换为 1 天?” :不。它适用于
(small)datetime
,但对于现代数据类型,它会生成错误。至于为什么它是
1
一天,很可能是 SQL Server 之前的东西,并且可能来自 Sybase(尽管我无法确认这一点)。为什么1
选择这一天,我不知道。也许是因为当时另一个应用程序做了类似的事情;例如,Excel 也做同样的事情,但它们的数字不一致(0
is1900-01-00
和1
is1900-01-01
,但是,由于将 1900 年视为闰年,所以后来漂移更多,所以今天45371
在 SQL Server 中,但45373
在 Excel 中)。如果不是因为其他应用程序,它可能是任意的。就像您在评论中提到的那样,类似的代码
GETDATE() + 1
很容易被视为不明确;什么是1
作为datetime
?如果用户期望它是其他东西(例如像纪元那样的第二个),那么很容易被原谅。现代日期和时间数据类型 、 和 (和 ) 中不
date
存在datetime2
此datetimeoffset
行为time
。数据类型不允许从数值到它们的显式或隐式转换。如果您尝试添加1
这样的日期,您会收到错误消息:事实上,最好的办法就是明确表达。有一个用于在日期(和时间)值中添加/减去时间段的函数:
DATEADD
。该函数适用于所有日期和时间数据类型(“新”和“旧”),并且语法非常明确:现在,没有人会认为上述内容是在系统日期和时间的当前值上添加 1 天以外的任何内容,这是可以原谅的。
CURRENT_TIMESTAMP
是 ANSI 兼容函数,返回与 SQL Server 函数相同的值,GETDATE()
这两个函数均派生自运行它们的计算机的操作系统。CURRENT_TIMESTAMP
可以与其他 ANSI 兼容的数据库一起使用,但GETDATE()
不能。除非我需要 UTC 日期,否则我会使用该
CURRENT_TIMESTAMP
表单,因为它实际上是带有日期/时间的时间戳 - 除非它被分配,例如:这两个都可以工作,但只是日期类型而不是日期时间它不仅仅是一个整数,因为这些都在 SQL Server 中工作。
为了明确目的,我总是建议使用,因为当您还需要小时或其他日期时间调整
DATEADD(DAY, 1, CURRENT_TIMESTAMP)
时,这也会变得更简单;DATEADD(HOUR, 8, CURRENT_TIMESTAMP)
DATEADD(MINUTE, 1400, CURRENT_TIMESTAMP)
你的问题的答案是肯定的。但不要依赖它。您还可以用 +0.25 添加 6 小时,因为这就是 SQL Server 中的内部表示方式。看起来很多文档都被清理了,但我看到了指定内部表示的旧文档。
许多年前,我记得通过将大量日期转换为浮动,进行平均并转换回来以获得平均日期来滥用此功能。但我想我今天不会这么做。
探索数据类型问题的一种方便的工具是
SQL_VARIANT_PROPERTY
:如果将两者组合在一个表达式中:
正如您所发现的,数据类型优先级和数据类型转换的规则表明,在前一个表达式中将发生从
int
到 的隐式转换。datetime
到目标数据类型的显式转换应提供相同的结果:以一种令人愉快的循环方式,这被记录为:
表达结果:
+(加法):
数据类型优先级:该表显示
datetime
(6) 的优先级高于int
(16)。这让您回到数据类型转换。
这应该意味着代码示例显示了预期的行为,并且
1
将隐式转换为一天作为datetime
. 明确的文档并不总是可用。旁白:另一个有用的检查地方是Constants。它对当前的问题保持沉默。