11

服务器:SQL Server 2012;SP1; 开发者版

代码:

declare @datetime datetime = '1900-01-01 00:00:00.000'

declare @time time = '11:11:11'

select @datetime + @time

当我在MASTER数据库中运行上面的代码时,我得到了错误:

消息 402,级别 16,状态 1,第 3 行数据类型 datetime 和 time 在 add 运算符中不兼容。

但是当它是任何其他数据库时,它可以工作!知道为什么这一定会发生吗?

PS - 在企业版中,无论数据库上下文如何,这都会引发错误。

4

3 回答 3

6

上述代码适用于 MS SqlServer 2008,但此代码不适用于 MS SqlServer 2012 或更高版本。我遇到了同样的问题并像这样解决它。

DECLARE @today_start datetime
DECLARE @dail_time time   

SELECT @today_start = convert(datetime, @dayStr,103) + CAST(@dail_time as DATETIME)
于 2016-01-25T03:42:43.687 回答
3

实际上,添加日期和时间时没有合理的行为,除非您知道这两个值的时区。其他数据库可能会假设一些任意的默认时区,但 SQL Server 不会。

如果 T-SQL 设计者添加了这种支持,大多数旧代码(服务器端和客户端)都会因难以检测的错误而崩溃。请记住,假设某些默认时区(本地或 GMT),大多数人仍然使用旧的日期时间类型。

您可能会争辩说应该可以添加datetimeoffset时间,因为第一个包含时区信息而第二个不包含,但我认为 T-SQL 设计者希望在将一种数据类型转换为另一种时避免混淆。除非人们更改他们的客户端类型时区感知代码,否则许多客户端代码仍然会中断。

那么,为什么没有明确的函数来做加法呢?可能也不起作用,因为没有时区的日期时间类型会隐式转换为 datetimeoffset2。您可以轻松地将没有时区的值传递给此类函数,并且在将其传递给函数之前,它将被转换为错误的时区

简而言之,向后兼容性并没有提供处理日期+时间添加的安全方式。

于 2013-08-26T10:09:04.070 回答
0

错误 402 可能发生在数据库兼容级别110 或更高级别:

ALTER DATABASE testdb
SET COMPATIBILITY_LEVEL = 110;
GO
USE testdb;
DECLARE @datetime DATETIME = '1900-01-01T00:00:00';
DECLARE @time TIME = '11:11:11';
SELECT @datetime + @time;
消息 402,第 16 层,状态 1,第 7 行
数据类型 datetime 和 time 在 add 运算符中不兼容。

但是,它不会出现在 100 或更低:

ALTER DATABASE testdb
SET COMPATIBILITY_LEVEL = 100;
GO
USE testdb;
DECLARE @datetime DATETIME = '1900-01-01T00:00:00';
DECLARE @time TIME = '11:11:11';
SELECT @datetime + @time;
1900-01-01 11:11:11.000

您的主数据库可能具有兼容性级别 110 (SQL Server 2012),而您测试的其他数据库的兼容性级别较低。(例如,由于使用以前版本的 SQL Server 的备份进行恢复)

注意:此更改似乎没有记录在案。我已经打开MicrosoftDocs/sql-docs#7152来记录它。

于 2021-12-31T23:33:18.957 回答