【问题标题】:SQL Server Date and Time Format using strings使用字符串的 SQL Server 日期和时间格式
【发布时间】:2019-06-10 08:51:55
【问题描述】:

我一直认为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 server 配置为使用:

|------------------|------------------------------|
| 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,那么这个确实会返回预期的数据。

【问题讨论】:

    标签: sql-server datetime format


    【解决方案1】:

    对于 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-03-11
      • 2021-12-21
      • 2013-08-09
      • 1970-01-01
      • 1970-01-01
      • 2017-06-14
      相关资源
      最近更新 更多