使用字符串的SQL Server日期和时间格式

时间:2019-06-10 08:51:55

标签: sql-server datetime format

我总是给人以datetime数据类型的印象,因为2019-07-06始终是2019年7月6日,而不考虑区域设置和区域设置,即这是通用的日期时间格式。

但是,我遇到了一种情况,我试图从数据库中查询某些数据,而字符串2019-07-06无法返回预期的结果。但是2019-06-07将。

我一直都认为YYYY-MM-DD格式是基于ISO-8601的。

鉴于这是我在6月7日星期五插入数据的地方,今天我正在查询该数据,我看到:

query result

使用查询

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,则此返回期望的数据。

1 个答案:

答案 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"

顺便说一句,在使用DATEDATETIME2时,这种格式没有歧义,但是DATETIMESMALLDATETIME一直存在这种歧义。亚伦·伯特兰(Aaron Bertrand)在他的不良习惯(踢踢系列)中写了此文章:mis-handling date / range queries