SQL Server формат даты и времени с использованием строк - PullRequest
2 голосов
/ 10 июня 2019

Я всегда находился под впечатлением, учитывая тип данных datetime, так как 2019-07-06 всегда был 6 июля 2019 года, независимо от региональных и региональных настроек, то есть это универсальный формат даты и времени.

Однако я столкнулся с ситуацией, когда я пытаюсь запросить некоторые данные из нашей базы данных, и строка 2019-07-06 не возвращает ожидаемых результатов. Однако 2019-06-07 будет.

Я всегда понимал, что формат YYYY-MM-DD основан на ISO-8601 .

Учитывая, что это было в пятницу, 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, тогда это DOES вернет ожидаемые данные.

1 Ответ

4 голосов
/ 10 июня 2019

С типом DATETIME литерал 2019-06-07 может быть 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"

В качестве альтернативы выполните явное преобразование и используйте параметр style для обеспечения согласованного преобразования:

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. Аарон Бертран писал об этом в своих «Плохих привычках»: неправильная обработка запросов даты / диапазона

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...