2016-11-29 3 views
3

Я использовал этот формат в течение многих лет укоротить даты и времяУсечения даты + времени использования Datetime2

SELECT DATEADD(HOUR, DATEDIFF(HOUR, 0, '1980-02-05 12:45'), 0) AS Hour , 
     DATEADD(DAY, DATEDIFF(DAY, 0, '1980-02-05 12:45'), 0) AS Day , 
     DATEADD(MONTH, DATEDIFF(MONTH, 0, '1980-02-05 12:45'), 0) AS Month , 
     DATEADD(YEAR, DATEDIFF(YEAR, 0, '1980-02-05 12:45'), 0) AS Year; 

Но у меня есть необходимость хранить очень ранние сроки, как 1400-01-01 и поэтому я могу использовать DateTime2.

Но как бы я поддерживал способность по-прежнему усекать, как показано выше, используя DateTime2?

Изменение год выше 1400 от 1980 будет приводить к

SELECT DATEADD(HOUR, DATEDIFF(HOUR, 0, '1400-02-05 12:45'), 0) AS Hour , 
     DATEADD(DAY, DATEDIFF(DAY, 0, '1400-02-05 12:45'), 0) AS Day , 
     DATEADD(MONTH, DATEDIFF(MONTH, 0, '1400-02-05 12:45'), 0) AS Month , 
     DATEADD(YEAR, DATEDIFF(YEAR, 0, '1400-02-05 12:45'), 0) AS Year; 

Преобразование типа данных VARCHAR к типу DateTime данных привело в значении вне-диапазона.

ТАК литье до DateTime2

SELECT DATEADD(HOUR, DATEDIFF(HOUR, 0, CAST('1400-02-05 12:45' AS DATETIME2)),0) AS Hour , 
     DATEADD(DAY, DATEDIFF(DAY, 0, CAST('1400-02-05 12:45' AS DATETIME2)),0) AS Day , 
     DATEADD(MONTH, DATEDIFF(MONTH, 0, CAST('1400-02-05 12:45' AS DATETIME2)), 0) AS Month , 
     DATEADD(YEAR, DATEDIFF(YEAR, 0, CAST('1400-02-05 12:45' AS DATETIME2)), 0) AS Year; 

превращения типа datetime2 данных в тип данных даты и времени привело к значению вне-диапазона.

Я предполагаю, что 0 в настоящее время рассматривается как тип DateTime данных и effectly приведения его в DateTime.

Пытаясь забрасывать 0 к DateTime2 с помощью CAST(0 AS DATETIME2) дает мне эту ошибку

Явное преобразование типа данных междунар в datetime2 не допускается.

В конце концов я желающий использовать их как сохранялся столбцы в таблице, которые работали отлично с DateTime типов данных, но не так просто с DateTime2

+1

Совет. Полезно пометить вопросы базы данных как с помощью соответствующего программного обеспечения (MySQL, Oracle, DB2, ...) и версии, например. 'SQL-сервер-2014'. Различия в синтаксисе и особенностях часто влияют на ответы, например. [ 'DateFromParts'] (https://msdn.microsoft.com/en-us/library/hh213228.aspx). – HABO

ответ

1

Try использовать:

DECLARE @Default DATETIME2 = CAST('' AS DATETIME2) 
SELECT DATEADD(HOUR, DATEDIFF(HOUR, @Default, CAST('1400-02-05 12:45' AS DATETIME2)), @Default) AS Hour , 
     DATEADD(DAY, DATEDIFF(DAY, @Default, CAST('1400-02-05 12:45' AS DATETIME2)), @Default) AS Day , 
     DATEADD(MONTH, DATEDIFF(MONTH, @Default, CAST('1400-02-05 12:45' AS DATETIME2)), @Default) AS Month , 
     DATEADD(YEAR, DATEDIFF(YEAR, @Default, CAST('1400-02-05 12:45' AS DATETIME2)), @Default) AS Year; 
+0

Спасибо за вашу помощь, но у меня теперь есть проблема с этими формулами, которые не детерминированы и не могут быть сохранены в базе данных. ALTER TABLE ADD dbo.QuakeRawJSON \t [Дата] AS (DateAdd (день, DateDiff (день, CAST ('' AS Datetime2), origintime), CAST ('' AS Datetime2))) сохранялось Msg 4936 , Уровень 16, состояние 1, строка 1 Вычисленный столбец «Дата» в таблице «QuakeRawJSON» не может быть сохранен, потому что столбец не является детерминированным. –

2

You следует использовать определенную базовую дату вместо 0. 0 может быть неявно преобразован в тип datetime. Для datetime2 такое неявное преобразование не допускается. Кроме того, базовая дата должна иметь тип datetime2. Тогда DATEDIFF и DATEADD будут работать с datetime2 значениями.

Еще одна причина использования явной базовой даты заключается в том, что эта базовая дата должна быть первым днем ​​года и иметь 00:00:00 время для правильной работы формулы. Неявные даты начала, например 0, преобразованные в datetime или '', преобразованные в datetime2, также имеют эти свойства прямо сейчас, но действительно ли вы хотите полагаться на внутренние детали реализации типа? Лучше четко изложить такие вещи, и это облегчает понимание формулы для нового человека.

Кроме того, если вы когда-либо захотите усечь границу недели, используя тот же подход, вам нужно будет выбрать базовую дату, которая находится в понедельник (если ваша неделя начинается в понедельник) или в воскресенье (если ваша неделя начинается с Воскресенье). Формула остается неизменной, но основная дата важна.

Пример 1 - работы

DECLARE @VarBase datetime2 = '2000-01-01'; 
DECLARE @VarValue datetime2 = '1400-02-05 12:45'; 

SELECT 
    DATEADD(HOUR, DATEDIFF(HOUR, @VarBase, @VarValue), @VarBase) AS Hour, 
    DATEADD(DAY, DATEDIFF(DAY, @VarBase, @VarValue), @VarBase) AS Day, 
    DATEADD(MONTH, DATEDIFF(MONTH, @VarBase, @VarValue), @VarBase) AS Month, 
    DATEADD(YEAR, DATEDIFF(YEAR, @VarBase, @VarValue), @VarBase) AS Year; 

Пример 2 - работы

SELECT 
    DATEADD(HOUR, DATEDIFF(HOUR, @VarBase, '1400-02-05 12:45'), @VarBase) AS Hour, 
    DATEADD(DAY, DATEDIFF(DAY, @VarBase, '1400-02-05 12:45'), @VarBase) AS Day, 
    DATEADD(MONTH, DATEDIFF(MONTH, @VarBase, '1400-02-05 12:45'), @VarBase) AS Month, 
    DATEADD(YEAR, DATEDIFF(YEAR, @VarBase, '1400-02-05 12:45'), @VarBase) AS Year; 

Пример 3 - не работает

SELECT 
    DATEADD(HOUR, DATEDIFF(HOUR, '2000-01-01', '1400-02-05 12:45'), '2000-01-01') AS Hour, 
    DATEADD(DAY, DATEDIFF(DAY, '2000-01-01', '1400-02-05 12:45'), '2000-01-01') AS Day, 
    DATEADD(MONTH, DATEDIFF(MONTH, '2000-01-01', '1400-02-05 12:45'), '2000-01-01') AS Month, 
    DATEADD(YEAR, DATEDIFF(YEAR, '2000-01-01', '1400-02-05 12:45'), '2000-01-01') AS Year; 

Добавление значения в столбец 'datetime' вызвало переполнение.

Это не работает, потому что буквальный 2000-01-01 превращается в datetime, не datetime2.

Пример 4 - работы

SELECT 
    DATEADD(HOUR, DATEDIFF(HOUR, CAST('2000-01-01' AS datetime2), '1400-02-05 12:45'), CAST('2000-01-01' AS datetime2)) AS Hour, 
    DATEADD(DAY, DATEDIFF(DAY, CAST('2000-01-01' AS datetime2), '1400-02-05 12:45'), CAST('2000-01-01' AS datetime2)) AS Day, 
    DATEADD(MONTH, DATEDIFF(MONTH, CAST('2000-01-01' AS datetime2), '1400-02-05 12:45'), CAST('2000-01-01' AS datetime2)) AS Month, 
    DATEADD(YEAR, DATEDIFF(YEAR, CAST('2000-01-01' AS datetime2), '1400-02-05 12:45'), CAST('2000-01-01' AS datetime2)) AS Year; 
+0

Спасибо, но у меня сейчас проблема, не детерминированная. Смотрите мой комментарий на тему @MegaTron –

+0

@ChrisCrowe, я рад, что вы поняли, что использование 'CONVERT' вместо' CAST' решает проблему. –

1

Я обнаружил, что вместо того, чтобы использовать CAST ('DateTimeData' как Datetime2), если я использую Преобразование может быть детерминированным результатом.

Как указана на этом посте: Cannot persist computed column - not deterministic

ALTER TABLE dbo.QuakeRawJSON 
ADD [Date] AS (DATEADD(DAY,DATEDIFF(DAY, CONVERT(DATETIME2,'',112) 
       ,origintime),CONVERT(DATETIME2,'',112))) PERSISTED; 

Спасибо за вашу помощь.

Смежные вопросы