Сравнение строк SQL Server UTC не работает

#sql #sql-server #timezone

#sql #sql-сервер #Часовой пояс

Вопрос:

у нас есть два сервера SQL.

У нас есть следующий пример SQL для воссоздания проблемы, с которой мы сталкиваемся.

 select * from (

select '2020-11-04 08:00:00' as start
union all
select '2020-11-04 08:00:00' as start

) a

where cast(convert(date, a.start) as datetime)   cast(Cast(a.start AS time) as datetime) > '2020-11-04 08:00:00'

  

когда мы выполняем этот запрос к серверам, один сервер возвращает две записи, а другой возвращает ноль записей.

Оба должны возвращать нулевые записи.

Мы думаем, что есть некоторые настройки, которые необходимо настроить на сервере, чтобы исправить это. Не могли бы вы нам помочь? Спасибо

Комментарии:

1. Зачем голосовать за закрытие?? Обратная связь приветствуется.

2. Потому что у вас слишком много репутации / опыта, чтобы опубликовать это, не предпринимая никаких реальных попыток отладки. Первое, что вы должны сделать, это удалить предложение where и добавить все выражения, используемые в нем, в список выбора, чтобы фактически УВИДЕТЬ, что вычисляет ваша логика. Но зачем беспокоиться обо всех приведениях и математике? Опубликованные вами значения могут быть напрямую и безопасно преобразованы в datetime одним приведением. И поскольку ваш вопрос не имеет никакого отношения к UTC в опубликованном виде, это говорит о том, что ваша фактическая проблема может быть совсем другой.

3. У строк нет часового пояса, у дат есть. Для начала не обрабатывайте даты как строки. Если вы заботитесь о часовых поясах, используйте datetimeoffset . Даты также не имеют формата, они являются двоичными значениями.

4. Кстати, какой смысл отдельно анализировать компоненты даты? Вы пытались обойти локализованный синтаксический анализ, используемый datetime ? Вы могли бы использовать datetime2 вместо eg cast(a.date as datetime2(0)) или datetimeoffset , например cast(a.date as datetimeoffset(0)) . Это сгенерирует datetimeoffset в часовом поясе сервера.

5. Я сделал попытку, после того, как я не смог понять, я опубликовал этот вопрос. Проблема заключалась в том, что я предположил, что ‘гггг-ММ-дд чч: мм: сс’ был UTC, и SQL интерпретировал бы его как UTC, как это было, когда язык был установлен на us-english, но оказалось, что мое понимание было неверным.

Ответ №1:

Я подозреваю, что серверы имеют разные базовые языки / настройки для дат — хотя, очевидно, это всего лишь предположение.

Можно 2020-11-04 08:00:00 считать 8:00 утра 4 ноября, тогда как другой рассматривает его как 11 апреля.

Они могут быть основаны на

  • Региональные настройки Windows
  • Язык SQL Server по умолчанию

Вы должны использовать универсальный формат даты и времени, например, 20201104 08:00:00 . Если вы измените приведенный выше запрос, чтобы использовать их, и серверы вернут тот же ответ, что и друг другу, я думаю, вы нашли проблему.

Конечно, серверы могут находиться в разных часовых поясах и / или не учитывать переход на летнее время, но SELECT getdate() я должен сообщить вам, какие даты на сервере.

Комментарии:

1. Гораздо лучшим решением было бы использовать правильные значения даты вместо строк. Даты не имеют формата и не зависят от языкового стандарта сервера, они представляют собой двоичные значения. Если часовые пояса важны, правильный тип datetimeoffset .

2. Полностью согласен с @Panagiotis — отсюда и утверждение, что они должны использовать универсальный формат.

3. Я сказал обратное — что никакие строки вообще не должны использоваться. datetime не имеет формата, это двоичное значение

4. Извините, я не понимаю @Panagiotis — где используется строка? Вы имеете в виду кавычки вокруг дат? Если да, то как можно приступить к работе без указания даты? CREATE TABLE #d (d date); INSERT INTO #d (d) SELECT '20201104';

5. Похоже, на одном из наших серверов был установлен язык «us-english» и «British». Британский нужно изменить на «us-english». У меня сложилось впечатление, что «2020-11-01 00:00:00» был универсальным форматом, т.Е. iso 1860, поэтому я предположил, что sql интерпретирует это как UTC.