Вопрос

Который из них:

является в рекомендуемый способ хранения даты и времени в SQL Server 2008+?

Я знаю о различиях в точности (и, вероятно, пространстве для хранения), но пока игнорирую их, есть ли документ с наилучшей практикой о том, когда и что использовать, или, может быть, нам следует просто использовать datetime2 только?

Это было полезно?

Решение

Документация MSDN для дата - время рекомендует использовать дата - время2.Вот их рекомендация:

Используйте time, date, datetime2 и datetimeoffset типы данных для нового работа.Эти типы соответствуют стандарту SQL .Они более портативны. time, datetime2 и datetimeoffset обеспечьте большую точность в секундах. datetimeoffset обеспечивает часовой пояс поддержка глобально развернутых приложений.

datetime2 имеет больший диапазон дат, большую дробную точность по умолчанию и необязательную точность, заданную пользователем.Также, в зависимости от заданной пользователем точности, он может использовать меньше памяти.

Другие советы

DATETIME2 имеет диапазон дат от "0001 / 01 / 01" до "9999 / 12 / 31", в то время как DATETIME тип поддерживает только 1753-9999 годы выпуска.

Кроме того, если вам нужно, DATETIME2 может быть более точным с точки зрения времени;ДАТА-ВРЕМЯ ограничено 3 1/3 миллисекунды, в то время как DATETIME2 может быть с точностью до 100 нс.

Оба типа сопоставляются с System.DateTime в .NET - никакой разницы нет.

Если у вас есть выбор, я бы рекомендовал использовать DATETIME2 когда это возможно.Я не вижу никаких преимуществ в использовании DATETIME (за исключением обратной совместимости) - у вас будет меньше проблем (с выходом за пределы диапазона дат и тому подобными хлопотами).

Plus:если вам нужна только дата (без временной части), используйте DATE - это так же хорошо, как DATETIME2 и к тому же экономит вам место!:-) То же самое касается только времени - используйте TIME.Вот для чего существуют эти типы!

дата - время2 выигрывает по большинству аспектов, за исключением (совместимость со старыми приложениями)

  1. более крупный диапазон значений
  2. лучше Точность
  3. меньший место для хранения (если указана необязательная пользовательская точность)

SQL Date and time data types compare - datetime,datetime2,date,TIME

пожалуйста, обратите внимание на следующие моменты

  • Синтаксис
    • datetime2[(точность в доли секунды => Смотрите ниже размер хранилища)]
  • Точность, масштаб
    • от 0 до 7 цифр, с точностью до 100 нс.
    • Точность по умолчанию составляет 7 цифр.
  • Размер хранилища
    • 6 байт для точности менее 3;
    • 7 байт для точности 3 и 4.
    • Вся остальная точность требуется 8 байт.
  • Дата-время2(3) имеет то же количество цифр, что и DateTime, но использует 7 байт памяти вместо 8 байт (SQLHINTS- DateTime Против DateTime2)
  • Узнайте больше на datetime2(статья Transact-SQL MSDN)

источник изображения :Набор для самостоятельного обучения MCTS (экзамен 70-432):Microsoft® SQL Server® 2008 - Внедрение и обслуживание Глава 3: Таблицы -> Урок 1:Создание таблиц -> страница 66

Я согласен с @marc_s и @Adam_Poward - DateTime2 является предпочтительным методом продвижения вперед.Он имеет более широкий диапазон дат, более высокую точность и использует равный или меньший объем памяти (в зависимости от точности).

Однако в ходе обсуждения была упущена одна вещь...
@Marc_s заявляет: Both types map to System.DateTime in .NET - no difference there.Это правильно, однако обратное неверно... и это имеет значение при выполнении поиска в диапазоне дат (например"найдите мне все записи, измененные 5/5/2010").

Версия .NET для Datetime имеет такой же диапазон и точность, как DateTime2.При сопоставлении .net Datetime вплоть до старого SQL DateTime ан происходит неявное округление.Старый SQL DateTime с точностью до 3 миллисекунд.Это означает , что 11:59:59.997 это настолько близко, насколько вы можете приблизиться к концу дня.Все, что выше, округляется в большую сторону до следующего дня.

Попробуй это :

declare @d1 datetime   = '5/5/2010 23:59:59.999'
declare @d2 datetime2  = '5/5/2010 23:59:59.999'
declare @d3 datetime   = '5/5/2010 23:59:59.997'
select @d1 as 'IAmMay6BecauseOfRounding', @d2 'May5', @d3 'StillMay5Because2msEarlier'

Избежание этого неявного округления является важной причиной для перехода к DateTime2.Неявное округление дат явно вызывает путаницу:

Почти во всех ответах и комментариях было много плюсов и мало минусов.Вот краткое изложение всех плюсов и минусов на данный момент, плюс некоторые важные минусы (в # 2 ниже) Я видел упомянутое только один раз или вообще не видел.

  1. ПЛЮСЫ:

1.1.Более совместимый с ISO (ISO 8601) (хотя я не знаю, как это реализуется на практике).

1.2.Больший диапазон (от 1/1/0001 до 12/31/9999 по сравнению1/1/1753-12/31/9999) (хотя дополнительные диапазоны, все до 1753 года, вероятно, не будут использоваться, за исключением, например, исторических, астрономических, геологических и т.д.приложения).

1.3.Точно соответствует диапазону .NET-х DateTime Диапазон типа (хотя оба преобразуют туда и обратно без специального кодирования, если значения находятся в пределах диапазона и точности целевого типа, за исключением приведенного ниже Con # 2.1, иначе возникнет ошибка / округление).

1.4.Более высокая точность (100 наносекунд, или 0,000,000, 1 сек.против.3,33 миллисекунды, или 0,003,33 сек.) (хотя дополнительная точность, скорее всего, не будет использоваться, за исключением, например, инженерных / научных приложений).

1.5.При настройке для Похожие (как в 1 миллисекунде, а не "такой же" (как в 3,33 миллисекунде), как утверждал Иман Абиди) точность, как DateTime, занимает меньше места (7 против8 байт), но тогда, конечно, вы бы потеряли преимущество точности, которое, вероятно, является одним из двух (другое - диапазон) наиболее рекламируемых, хотя, вероятно, и ненужных преимуществ).

  1. МИНУСЫ:

2.1.При передаче параметра в .NET SqlCommand, вы должны указать System.Data.SqlDbType.DateTime2 если вы, возможно, передаете значение за пределы SQL Server DateTimeдиапазон и / или точность, поскольку по умолчанию используется System.Data.SqlDbType.DateTime.

2.2.Не может быть неявно / легко преобразовано в числовое значение с плавающей запятой (количество дней с момента минимальной даты-времени), чтобы выполнить с ним следующие действия в выражениях SQL Server, используя числовые значения и операторы:

2.2.1.добавьте или вычтите количество дней или неполных дней.Примечание:Используя DateAdd Функция в качестве обходного пути не является тривиальной, когда вам нужно учитывать несколько, если не все части даты-времени.

2.2.2.возьмите разницу между двумя датами-временем для целей расчета “возраста”.Примечание:Вы не можете просто использовать SQL Server DateDiff Функция вместо этого, потому что она не вычисляет age как и следовало ожидать большинству людей, если произойдет, что две даты-времени пересекут границу даты-времени календаря / часов для указанных единиц измерения, даже если для крошечной части этой единицы измерения, это вернет разницу как 1 от этой единицы измерения по сравнению0.Например, в DateDiff в Day’s из двух значений даты и времени с интервалом всего в 1 миллисекунду вернет 1 против0 (дней), если эти даты и время приходятся на разные календарные дни (т.е.“1999-12-31 23:59:59.9999999” и “2000-01-01 00:00:00.0000000”).Та же разница во времени даты в 1 миллисекунду, если ее переместить так, чтобы они не пересекали календарный день, вернет “DateDiff” в Day’s из 0 (дней).

2.2.3.возьмите тот Avg даты-времени (в агрегированном запросе) путем простого преобразования сначала в “Float”, а затем обратно в DateTime.

ПРИМЕЧАНИЕ:Для преобразования DateTime2 для числового значения вам нужно выполнить что-то вроде следующей формулы, которая по-прежнему предполагает, что ваши значения не меньше 1970 года (что означает, что вы теряете весь дополнительный диапазон плюс еще 217 лет.Примечание:Возможно, вы не сможете просто настроить формулу, чтобы учесть дополнительный диапазон, поскольку можете столкнуться с проблемами переполнения чисел.

25567 + (DATEDIFF(SECOND, {d '1970-01-01'}, @Time) + DATEPART(nanosecond, @Time) / 1.0E + 9) / 86400.0 – Источник:“ https://siderite.blogspot.com/2015/08/how-to-translate-t-sql-datetime2-to.html

Конечно, вы также могли бы Cast Для DateTime сначала (и при необходимости снова вернуться к DateTime2), но вы потеряли бы преимущества точности и дальности (все до 1753 года) DateTime2 против. DateTime которые, вероятно, являются 2 самыми большими и в то же время, вероятно, 2 наименее необходимыми, что вызывает вопрос, зачем использовать это, когда вы теряете неявные / простые преобразования в числовые значения с плавающей запятой (количество дней) для сложения / вычитания / "возраста" (против DateDiff) / Avg вычисляет выгоду, которая, по моему опыту, является большой.

Кстати, в Avg даты-времени является (или, по крайней мере, следует быть) важным вариантом использования.а) Помимо использования для получения средней продолжительности, когда для представления продолжительности используются значения даты и времени (начиная с общей базовой даты и времени) (обычная практика), б) также полезно получать статистику типа панели мониторинга о том, какое среднее значение даты и времени находится в столбце дата-время диапазона / группы строк.в) стандарт (или, по крайней мере, следует быть стандартным) специальный запрос для мониторинга / устранения неполадок значений в столбце, который может быть недействительным когда-либо / дольше и / или, возможно, должен устареть, заключается в перечислении для каждого значения количества встречаемости и (если доступно) Min, Avg и Max метки даты и времени, связанные с этим значением.

DateTime2 наносит ущерб, если вы являетесь разработчиком Access, пытающимся записать Now() в рассматриваемое поле.Только что выполнил миграцию Access -> SQL 2008 R2, и она поместила все поля datetime в качестве DateTime2.Добавление записи с помощью Now() в качестве разбомбленного значения.Это было нормально 1/1/2012, 2: 53: 04 вечера, но не 1/10/2012, 2:53: 04 вечера.

Когда-то характер имел значение.Надеюсь, это кому-нибудь поможет.

Вот пример, который покажет вам различия в размере хранилища (байты) и точности между smalldatetime, datetime, datetime2(0) и datetime2(7):

DECLARE @temp TABLE (
    sdt smalldatetime,
    dt datetime,
    dt20 datetime2(0),
    dt27 datetime2(7)
)

INSERT @temp
SELECT getdate(),getdate(),getdate(),getdate()

SELECT sdt,DATALENGTH(sdt) as sdt_bytes,
    dt,DATALENGTH(dt) as dt_bytes,
    dt20,DATALENGTH(dt20) as dt20_bytes,
    dt27, DATALENGTH(dt27) as dt27_bytes FROM @temp

который возвращает

sdt                  sdt_bytes  dt                       dt_bytes  dt20                 dt20_bytes  dt27                         dt27_bytes
2015-09-11 11:26:00  4          2015-09-11 11:25:42.417  8         2015-09-11 11:25:42  6           2015-09-11 11:25:42.4170000  8

Поэтому, если я хочу сохранить информацию с точностью до секунды, но не до миллисекунды, я могу сэкономить по 2 байта каждый, если использую datetime2(0) вместо datetime или datetime2(7).

Интерпретация строк даты в datetime и datetime2 может отличаться и при использовании неамериканских DATEFORMAT Настройки.Например.

set dateformat dmy
declare @d datetime, @d2 datetime2
select @d = '2013-06-05', @d2 = '2013-06-05'
select @d, @d2

Это возвращает 2013-05-06 (т.е.6 мая) для datetime, и 2013-06-05 (т.е.5 июня) для datetime2.Однако, с dateformat установить на mdy, оба @d и @d2 Возврат 2013-06-05.

В datetime поведение кажется противоречащим Документация MSDN из SET DATEFORMAT какие государства: Некоторые форматы символьных строк, например ISO 8601, интерпретируются независимо от настройки DATEFORMAT.Очевидно, что это неправда!

Пока меня это не укусило, я всегда думал, что yyyy-mm-dd даты просто будут обрабатываться правильно, независимо от настроек языка / локали.

в то время как наблюдается повышенный точность с дата - время2, некоторые клиенты не поддерживают Дата, время, или дата - время2 и заставит вас преобразовать в строковый литерал.В частности, Microsoft упоминает проблемы ODBC "нижнего уровня", OLE DB, JDBC и SqlClient с этими типами данных и имеет диаграмма показывая, как каждый из них может сопоставить тип.

Если значение совместимость сверхточность, используйте дата - время

Старый вопрос...Но я хочу добавить кое-что, о чем здесь еще никто не говорил...(Примечание:Это мое собственное наблюдение, так что не просите никаких ссылок)

Datetime2 выполняется быстрее, когда используется в критериях фильтрации.

TLDR ( ДВУ ):

В SQL 2016 у меня была таблица со ста тысячами строк и столбцом datetime ENTRY_TIME, потому что требовалось хранить точное время с точностью до секунд.При выполнении сложного запроса со многими объединениями и вложенным запросом, когда я использовал предложение where как:

WHERE ENTRY_TIME >= '2017-01-01 00:00:00' AND ENTRY_TIME < '2018-01-01 00:00:00'

Изначально запрос был в порядке, когда в нем были сотни строк, но когда количество строк увеличилось, запрос начал выдавать эту ошибку:

Execution Timeout Expired. The timeout period elapsed prior
to completion of the operation or the server is not responding.

Я удалил предложение where, и неожиданно запрос был выполнен за 1 секунду, хотя теперь были извлечены ВСЕ строки для всех дат.Я запустил внутренний запрос с предложением where, и это заняло 85 секунд, а без предложения where это заняло 0,01 секунды.

Я наткнулся здесь на множество тем по этому вопросу, таких как производительность фильтрации по дате и времени

Я немного оптимизировал запрос.Но реальную скорость я получил, изменив столбец datetime на datetime2.

Теперь тот же запрос, у которого ранее истекло время ожидания, занимает меньше секунды.

ваше здоровье

Согласно эта статья, если вы хотели бы иметь такую же точность DateTime , используя DateTime2 , вам просто нужно использовать DateTime2(3).Это должно обеспечить вам ту же точность, занимать на один байт меньше и обеспечивать расширенный диапазон.

Я только что наткнулся на еще одно преимущество для DATETIME2:это позволяет избежать ошибки в Python adodbapi модуль, который взрывается, если стандартная библиотека datetime передается значение, которое имеет ненулевые микросекунды для DATETIME столбец, но работает нормально, если столбец определен как DATETIME2.

Select ValidUntil + 1
from Documents

Приведенный выше SQL не будет работать с полем DateTime2.Он возвращает и выдает ошибку "Столкновение типов операндов:datetime2 несовместим с int"

Добавление 1 для получения следующего дня - это то, что разработчики делали с датами в течение многих лет.Теперь у Microsoft есть супер новое поле datetime2, которое не может обрабатывать эту простую функциональность.

"Давайте использовать этот новый тип, который хуже старого", я так не думаю!

Я думаю, что DATETIME2 является лучшим способом хранения date, потому что он обладает большей эффективностью, чем тот DATETIMESQL Server 2008 вы можете использовать DATETIME2, он сохраняет дату и время, занимает 6-8 bytes для хранения и имеет точность 100 nanoseconds.Таким образом, любой, кому нужна большая точность во времени, захочет DATETIME2.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top