仅更新日期时间字段日期

时间:2013-06-04 11:57:31

标签: sql sql-server

多年前,从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')

现在假设我有来自select的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

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

6 个答案:

答案 0 :(得分: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是“零”时间。

如果有时DateTimeField1具有正确的日期但DateTimeField2没有,则您可能希望将其作为两个单独的查询执行。

答案 1 :(得分: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 Serverdatetime存储为float,其中右侧是时间,左侧是日期。此查询将正确日期时间左侧的错误日期时间的左侧替换为

答案 2 :(得分:0)

我相信您只想更新DateTimeField1&amp; 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');

答案 3 :(得分: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')

答案 4 :(得分: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,因此您只需将两者一起添加即可。

答案 5 :(得分: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),但它仍然有效。