1

几年前,从 MSSQL 6.5 到 MSSQL 2000 的转换已经完成,而他们就在本周意识到转换无法转换某些日期时间列。现在我的任务是解决这个问题,我一直在摸索如何保存一些我知道是准确的信息。这是我需要修复的一张表的结构。

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 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

关于如何实现这一目标的任何想法?

4

6 回答 6

1

如果一个字段始终是 1900-01-01 但具有正确的时间,而另一个字段是 12:00:00 AM 但具有正确的日期,您可以将它们加在一起。

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

请参阅此 SQL Fiddle

1900-01-01 是“零”日期,因此如果将其添加到其他日期,则会得到相同的值。12:00:00 AM 是“零”时间。

如果在某些情况下 DateTimeField1 具有正确的日期但 DateTimeField2 没有,您可能希望将其作为两个单独的查询来执行。

于 2013-06-04T12:13:13.130 回答
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存储datetimefloat,其中右侧是时间,左侧是日期。此查询将错误日期时间的左侧替换为正确日期时间的左侧

于 2013-06-04T12:13:14.847 回答
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');
于 2013-06-04T12:23:01.013 回答
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')
于 2013-06-04T12:32:14.010 回答
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'

这是通过检查日期和时间是否转换为浮点数然后取整(删除时间部分)等于 1900 年 1 月 1 日来工作的。

由于 DateTimeField1 或 DateTimeField2 的日期部分本质上是 0,而 DateTimeField3 的时间部分是 0,您可以简单地将两者相加。

于 2013-06-04T14:14:17.037 回答
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部分是日期,小数部分是时间。所以通过floor(cast(DateTimeField3 as float))你得到日期部分,你可以简单地将它添加到 DateTimeField1 和 DateTimeField2,在你从它们中减去日期部分之后。对于 1900-01-01 日期部分将为零:select cast(0 as datetime),但它仍然可以工作。

于 2013-06-04T16:24:44.957 回答