我有一个数据强制之谜。我看到同一个查询有两种不同的行为,我无法理解为什么。
这是有问题的查询的相关部分的摘录,具有固定值。第一个值代表"今天"在我们的查询中,并使用相同的数据类型设置了显式CAST:
-- edited to change dates to ISO 8601 literal format to avoid ambiguity
SELECT DATEDIFF(dd,CAST('2014-03-24' AS SmallDateTime),'0001-01-01')
ISO 8601日期文字格式引文:https://msdn.microsoft.com/en-us/library/ms187819.aspx
我们在同一个SQL服务器实例上有两个不同的数据库。
其中一个返回零行,正如您所期望的那样。
服务器1返回关于' 1/1/0001'的日期范围的错误:
Msg 242,Level 16,State 3,Line 1
将varchar数据类型转换为日期时间数据类型会导致超出范围的值。
服务器2返回一个看起来正确的球场:
-735315
问题日期几乎肯定是' 1/1 / 0001'并且它因为我预期的默认日期时间而失败,因为它低于1753年1月1日的最小SQL日期时间(https://msdn.microsoft.com/en-us/library/ms187819.aspx)。
根据datediff(https://msdn.microsoft.com/en-US/library/ms189794(v=SQL.105).aspx)的MSDN页面,它可以接受以下值:
startdate is an expression that can be resolved to a time, date, smalldatetime, datetime, datetime2, or datetimeoffset
每个服务器的投射结果在服务器之间是相同的,并列在此处:
SELECT CAST('0001-01-01' As time) -- works: 00:00:00.0000000
SELECT CAST('0001-01-01' As date) -- works: 0001-01-01
SELECT CAST('0001-01-01' As smalldatetime) -- error: The conversion of a varchar data type to a smalldatetime data type resulted in an out-of-range value.
SELECT CAST('0001-01-01' As DateTime) -- error: The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.
SELECT CAST('0001-01-01' As datetime2) -- works: 0001-01-01 00:00:00.0000000
SELECT CAST('0001-01-01' As datetimeoffset) -- works: 0001-01-01 00:00:00.0000000 +00:00
错误显式地调用了失败的DateTime转换,因此这似乎是数据库1上的强制选择。
似乎数据库2使用不同的强制成功并正确地执行了约会数。
因为这两个数据库都在同一个SQL实例上,所以我排除了实例设置。
以下是我们想要检查的一些数据库设置,它们在两个数据库之间也是相同的(在SQL Server Management Studio中检查):
数据库整理(应该是每台服务器,但为了清楚起见,包括在内):
(database) > Right Click > Properties > General > Maintenance > Collation
Database one: SQL_Latin1_General_CP1_CI_AS
Database two: SQL_Latin1_General_CP1_CI_AS
启用日期关联优化:
(database) > Right Click > Properties > Options > Misc. > Date Correlation Optimization Enabled
Database one: False
Database two: False
两位数年份截止日期:
(database) > Right Click > Properties > Options > Containment > Two Digit Year Cutoff
Database one: 2049
Database two: 2049
用户选项日期格式
DBCC USEROPTIONS
Database one, dateformat: mdy
Database two, dateformat: mdy
(other settings appear identical)
我很乐意提供其他设置或测试查询结果,让我知道您希望看到的内容。
为什么这两个数据库对于这个相同的查询表现不同?为什么选择的胁迫似乎不同?
编辑:
答案 0 :(得分:0)
正如Aaron Bertrand在DBA堆栈交换站点上所回答的那样,这源于兼容性级别。
SELECT compatibility_level
FROM sys.databases WHERE name = 'FirstDatabase'
90
VS
SELECT compatibility_level
FROM sys.databases WHERE name = 'SecondDatabase'
110
Aaron在这个问题上有一个很好的写作原因: https://dba.stackexchange.com/questions/44908/what-is-the-actual-behavior-of-compatibility-level-80
请参阅涉及新日期/时间类型的转化
更高的兼容性级别可能意味着DateDiff使用DateTime2或其他更广泛的'数据类型和工作。在90或以下,它可能使用旧的DateTime,因此有转换错误。
感谢Tab Alleman提出的交叉建议。