我总是给人以datetime
数据类型的印象,因为2019-07-06
始终是2019年7月6日,而不考虑区域设置和区域设置,即这是通用的日期时间格式。
但是,我遇到了一种情况,我试图从数据库中查询某些数据,而字符串2019-07-06
无法返回预期的结果。但是2019-06-07
将。
我一直都认为YYYY-MM-DD
格式是基于ISO-8601的。
鉴于这是我在6月7日星期五插入数据的地方,今天我正在查询该数据,我看到:
使用查询
select
b.ID
, b.UserId
, b.EntryDate
, day(b.EntryDate) as 'day'
, month(b.EntryDate) as 'month'
from [dbo].[SomeTable] b
where b.UserId = 236328
但是当我更改查询时:
select
b.ID
, b.UserId
, b.EntryDate
, day(b.EntryDate) as 'day'
, month(b.EntryDate) as 'month'
from [dbo].[SomeTable] b
where b.UserId = 236328
and b.EntryDate > '2019-06-07'
这不会产生任何结果。但是更改EntryDate > '2019-07-06'
将返回我的数据。
注意::查询是在本地计算机上使用SSMS v18输入的。
SQL Server的当前版本为Microsoft SQL Server 2012 (SP4-GDR) (KB4057116) - 11.0.7462.6 (X64) Jan 5 2018 22:11:56 Copyright (c) Microsoft Corporation Developer Edition (64-bit) on Windows NT 6.3 <X64> (Build 9600: )
该sql服务器配置为使用:
|------------------|------------------------------|
| Setting | Value |
|------------------|------------------------------|
| Language | English (United States) |
| Default Language | British English |
| Server Collation | SQL_Latin1_General_CP1_CI_AS |
数据库配置为使用:
|---------------------|-----------------------|
| Setting | Value |
|---------------------|-----------------------|
| Collation | Latin1_General_CI_AS |
| Compatability Level | SQL Server 2012 (110) |
| Default Language | British English |
问题是,日期时间查询带有格式为YYYY-MM-dd
的字符串的预期行为是什么?我不记得过去20年以来的这种行为。
更新
作为记录,如果我在查询中输入日期时间为2019-06-07T00:00:00
,则此做返回期望的数据。
答案 0 :(得分:4)
使用DATETIME
类型时,文字2019-06-07
可能是6月7日或7月6日,具体取决于当前的DATEFORMAT
设置:
SET DATEFORMAT DMY;
SELECT FORMAT(CONVERT(DATETIME, '2019-06-07'), 'dd MMM yy');
--Returns "06 Jul 19"
SET DATEFORMAT MDY;
SELECT FORMAT(CONVERT(DATETIME, '2019-06-07'), 'dd MMM yy');
-- Returns "07 Jun 19"
为此,您不应该依赖默认服务器设置,避免这种歧义的最佳方法是使用格式yyyyMMdd
,无论设置如何,总是以相同的方式解释这种情况:
SET DATEFORMAT DMY;
SELECT FORMAT(CONVERT(DATETIME, '20190607'), 'dd MMM yy');
--Returns "07 Jun 19"
SET DATEFORMAT MDY;
SELECT FORMAT(CONVERT(DATETIME, '20190607'), 'dd MMM yy');
-- Returns "07 Jun 19"
或者,进行显式转换,并使用样式参数以确保转换一致:
SET DATEFORMAT DMY;
SELECT FORMAT(CONVERT(DATETIME, '2019-06-07', 101), 'dd MMM yy');
-- Returns "07 Jun 19"
SET DATEFORMAT MDY;
SELECT FORMAT(CONVERT(DATETIME, '2019-06-07', 101), 'dd MMM yy');
-- Returns "07 Jun 19"
顺便说一句,在使用DATE
或DATETIME2
时,这种格式没有歧义,但是DATETIME
和SMALLDATETIME
一直存在这种歧义。亚伦·伯特兰(Aaron Bertrand)在他的不良习惯(踢踢系列)中写了此文章:mis-handling date / range queries