2013-06-04 3 views
1

Несколько лет назад было выполнено преобразование из MSSQL 6.5 в MSSQL 2000, и на этой неделе они поняли, что преобразование не удалось преобразовать некоторые столбцы datetime. Теперь моя задача - исправить это, и я почесал голову, как я могу сохранить некоторые данные, которые, как я знаю, точны. Вот структура одной из таблиц, которую мне нужно исправить.Обновление дат только по дате только даты

DateTimeField1   DateTimeField2   DateTimeField3 
01/01/1900 5:50:00 PM 01/01/1900 5:52:00 PM 15/02/2005 12:00:00 AM 

Это один пример из многих записей, которые испорчены, к сожалению у меня нет доступа к любой резервной копии от до преобразования. Как вы можете видеть, часть даты является значением по умолчанию для поля DateTime и является частью, которую мне нужно исправить. У меня есть следующий select, который дает мне строки, которые мне нужно исправить.

SELECT DateTimeField1, DateTimeField2, DateTimeField3 
FROM Table1 
WHERE (DateTimeField1 < '20000101') OR (DateTimeField2 < '20000101') 

Предположим, у меня есть 60 записей, полученных в результате выбора. Мне нужно обновить эти записи только на основе DateTimeField3 DATE. Образец выше будет выглядеть;

DateTimeField1   DateTimeField2   DateTimeField3 
15/02/2005 5:50:00 PM 15/02/2005 5:52:00 PM 15/02/2005 12:00:00 AM 

Любая идея о том, как этого достичь?

+0

Вы имеете в виду точное время, а дату нет? – Aeronth

ответ

0

Я верю, что вы хотите обновить только DateTimeField1 & DateTimeField2, когда они меньше, чем '20000101'. CASE Заявление позаботится о том, чтобы не обновлять неправильное поле.

Попробуйте один запрос UPDATE -

SQL SERVER 2008 И ПОЗЖЕ -

UPDATE Table1 

SET DateTimeField1 = (CASE WHEN (DateTimeField1 < '20000101') 
         THEN CAST(CAST (DateTimeField3 AS DATE) AS DATETIME) 
         + CAST (DateTimeField1 AS TIME) 
         ELSE DateTimeField1 
        END) 
, DateTimeField2 = (CASE WHEN (DateTimeField2 < '20000101') 
         THEN CAST(CAST (DateTimeField3 AS DATE) AS DATETIME) 
         + CAST (DateTimeField2 AS TIME) 
         ELSE DateTimeField2 
        END) 
WHERE (DateTimeField1 < '20000101') OR (DateTimeField2 < '20000101'); 

РАНЬШЕ SQL SERVER 2008 -

UPDATE Table1 

SET DateTimeField1 = (CASE WHEN (DateTimeField1 < '20000101') 
         THEN DATEADD(DAY, 0, DATEDIFF(day, 0, DateTimeField3)) 
         + DATEADD(DAY, 0 - DATEDIFF(day, 0, DateTimeField1), DateTimeField1) 
         ELSE DateTimeField1 
       END) 
, DateTimeField2 = (CASE WHEN (DateTimeField2 < '20000101') 
         THEN DATEADD(DAY, 0, DATEDIFF(day, 0, DateTimeField3)) 
         + DATEADD(DAY, 0 - DATEDIFF(day, 0, DateTimeField2), DateTimeField2) 
         ELSE DateTimeField2 
       END) 
WHERE (DateTimeField1 < '20000101') OR (DateTimeField2 < '20000101'); 
+1

Спасибо Parag, который отлично работает :) – Mario

+0

Большинство приветствуется @Mario. Я рад, что решение помогло :) –

1

Если одно поле всегда 1900-01-01, но с правильным временем, а другое поле - 12:00:00, но с правильной датой, вы можете просто добавить их вместе.

UPDATE Test 
SET 
    DateTimeField1 = DateTimeField1 + DateTimeField3, 
    DateTimeField2 = DateTimeField2 + DateTimeField3 
WHERE (DateTimeField1 < '20000101') OR (DateTimeField2 < '20000101') 

См. this SQL Fiddle.

1900-01-01 - это «нулевая» дата, поэтому, если вы добавите ее к чему-то еще, вы получите то же значение. 12:00:00 AM - это «нулевое» время.

Если есть случаи, когда DateTimeField1 имеет правильную дату, но DateTimeField2 этого не делает, вы можете сделать это как два отдельных запроса.

+0

Добавление двух полей вместе - хорошая идея, но предложение where может вызвать некоторые обновления, которых не должно произойти. Использование отдельного запроса для каждого поля было бы более безопасным. –

+0

@Joe Этот запрос обновит оба поля, если только одно из полей неверно. Он должен обновлять неверное поле. Попробуйте изменить его с помощью инструкции 'CASE'. –

+0

Спасибо за ваше решение Джо. Как и другие, это не совсем то, что я ищу, но это дает мне отличную идею :) – Mario

0

Используйте этот запрос:

SELECT DateTimeField1 = 
    convert(datetime,convert(int,convert(float,t.DateTimeField3)) 
    + convert(float,t.DateTimeField1)), 
     DateTimeField2 = 
    convert(datetime,convert(int,convert(float,t.DateTimeField3)) 
    + convert(float,t.DateTimeField2)), 
FROM Table1 t 
WHERE (DateTimeField1 < '20000101') OR (DateTimeField2 < '20000101') 

SQL Server магазины datetime как float, где правая часть времени и левая сторона является дата. Этот запрос заменяет левую сторону неверного DateTime на левой сторону правильного DateTime

+0

Я считаю, что @Mario хочет обновить DateTimeField1 & DateTimeField2. Этот запрос обновляется только сначала. –

+0

Да Мне нужно обновить оба, infact, всего 6 полей, которые мне нужно проверить. Спасибо за ваше предложение. – Mario

+0

@ParagMeshram, на самом деле этот запрос ничего не обновляет. Этот запрос показывает способ решения проблемы. –

0

Попробуйте что-то вроде этого, он должен работа над MSSQL 2000

UPDATE tab SET DateTimeField1 = 
ltrim(str(datepart(year, DateTimeField3))) + '-' + 
ltrim(str(datepart(month, DateTimeField3))) + '-' + 
ltrim(str(datepart(day, DateTimeField3))) + ' ' + 
ltrim(str(datepart(hour, DateTimeField1))) + ':' + 
ltrim(str(datepart(minute, DateTimeField1))) + ':' + 
ltrim(str(datepart(second, DateTimeField1))) + '.' + 
ltrim(str(datepart(millisecond, DateTimeField1))) , 
DateTimeField2 = ltrim(str(datepart(year, DateTimeField3))) + '-' + 
ltrim(str(datepart(month, DateTimeField3))) + '-' + 
ltrim(str(datepart(day, DateTimeField3))) + ' ' + 
ltrim(str(datepart(hour, DateTimeField2))) + ':' + 
ltrim(str(datepart(minute, DateTimeField2))) + ':' + 
ltrim(str(datepart(second, DateTimeField2))) + '.' + 
ltrim(str(datepart(millisecond, DateTimeField2))) 
WHERE (DateTimeField1 < '20000101') OR (DateTimeField2 < '20000101') 
0

Это должно делать то, что вам нужно:

update <yourtable> 
set 
    DateTimeField1 = case when cast('1 jan 1900' as datetime) = cast(floor(cast(DateTimeField1 as float)) as datetime) then DateTimeField1 + DateTimeField3 else date1 end, 
    DateTimeField2 = case when cast('1 jan 1900' as datetime) = cast(floor(cast(DateTimeField2 as float)) as datetime) then DateTimeField2 + DateTimeField3 else date2 end 
where DateTimeField1 < '2 jan 1900' or DateTimeField2 < '2 jan 1900' 

Это работает, проверив, чтобы увидеть, если дату и время, преобразованной в поплавок, а затем этажной (который удаляет часть времени) равно 1-ое янв 1900 .

Как часть даты DateTimeField1 или DateTimeField2 по существу 0, а временная часть DateTimeField3 равна 0, вы можете просто добавить их вместе.

0

Самый простой способ сделать это было бы:

update Table1 
    set 
     DateTimeField1 = cast(cast(DateTimeField1 as float)-floor(cast(DateTimeField1 as float)) + floor(cast(DateTimeField3 as float)) as datetime 
    WHERE DateTimeField1 < '20000101' 

update Table1 
    set 
     DateTimeField2 = cast(cast(DateTimeField2 as float)-floor(cast(DateTimeField2 as float)) + floor(cast(DateTimeField3 as float)) as datetime 
    WHERE DateTimeField2 < '20000101' 

Я знаю, что бы работать на SQL Server 2005 и 2008, но я не уверен, издание 2000 года, так что проверить это первое.

Объяснение: datetime хранится как значение с плавающей точкой, где int part - дата, а десятичная часть - это время. Итак, по floor(cast(DateTimeField3 as float)) вы получаете дату, и вы можете просто добавить это в DateTimeField1 и DateTimeField2 после того, как вы вычитали из них дату. Для части даты 1900-01-01 будет ноль: select cast(0 as datetime), но он все равно будет работать.