2010-11-29 5 views
9

나는 이상하게 보이는 것을 보았습니다. datetime 열에 SQL Server를 저장하면 일부 DateTime 값이 부적절하게 반올림됩니다. 나는 뭔가를 놓치고 있다고 생각하지만, 나는 그것을 발견 할 수 없다. .NET 4.0을 사용하여 SQL Server 2008에 대해이 테스트를 실행하고 있습니다. 다음은 문제를 설명해야합니다.SQL Server에서 DateTime의 원치 않는 반올림

SQL Server에 Timestamps라는 테이블을 만들었습니다.

  1. 현재 시간을 가져옵니다 : 날짜 나는 또한 다음을 수행 간단한 테스트를 만든

    -
    타임 스탬프이 PK를 BIGINT, 아이덴티티 -

    ID : 그것은 두 개의 열이 있습니다 , 값을 밀리 초 정밀도로 자름

  2. 잘린 시간을 Timestamps
  3. DB에서 datetime` 값을 검색하여 원래의 (잘린) DateTime 객체와 비교했습니다. 나는 값이 다시 DB에서 반환에 잘린 값이 상당 할 것으로 예상하지만
public static void RoundTest() 
{ 
    DateTime preTruncation = DateTime.UtcNow; 
    DateTime truncated = preTruncation.TruncateToMilliseconds(); 

    using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["test"].ConnectionString)) 
    { 
     conn.Open(); 
     SqlCommand cmd = new SqlCommand(@"INSERT INTO Timestamps(timestamp) 
              VALUES(@savedTime); 
              SELECT SCOPE_IDENTITY() AS id"); 
     cmd.Parameters.Add(new SqlParameter("savedTime", truncated)); 
     cmd.Connection = conn; 
     var id = cmd.ExecuteScalar(); 

     SqlCommand get = new SqlCommand(@"SELECT timestamp FROM Timestamps 
              WHERE id = @id"); 

     get.Parameters.Add(new SqlParameter("id", id)); 
     get.Connection = conn; 
     DateTime retrieved = (DateTime)get.ExecuteScalar(); 

     if (retrieved != truncated) 
     { 
      Console.WriteLine("original: " + preTruncation.TimeOfDay); 
      Console.WriteLine("truncated: " + truncated.TimeOfDay); 
      Console.WriteLine("retrieved: " + retrieved.TimeOfDay); 
      Console.WriteLine(); 
     } 
    } 
} 

는, 항상 그런 것은 아니다.

original: 19:59:13.4049965 
truncated: 19:59:13.4040000 
retrieved: 19:59:13.4030000 

original: 19:59:14.4989965 
truncated: 19:59:14.4980000 
retrieved: 19:59:14.4970000 

original: 19:59:15.4749965 
truncated: 19:59:15.4740000 
retrieved: 19:59:15.4730000 

original: 19:59:30.1549965 
truncated: 19:59:30.1540000 
retrieved: 19:59:30.1530000 

TruncateToMilliseconds()는 다음과 같습니다 : 무엇 제공

public static DateTime TruncateToMilliseconds(this DateTime t) 
{ 
    return new DateTime(t.Year, t.Month, t.Day, t.Hour, t.Minute, t.Second, t.Millisecond); 
} 

여기에 몇 가지 샘플 출력입니다? 이것은 정말 부적절한 반올림인가, 아니면 여기서 잘못된 가정을하고 있습니까?

답변

13

날짜 시간은 3ms로 정확합니다. 따라서 3ms의 가장 가까운 배수로 반올림됩니다. 이를 극복하려면 datetime2을보십시오. 이것은 SQL2008 + 전용입니다.

EDIT : 3ms 밖에되지 않습니다. .000, .003 또는 .007 초 단위로 반올림합니다.

+1

실제로 날짜를 나타내는 두 개의 4 바이트 정수와 시계 틱 수를 나타내는 두 번째 4 바이트 정수로 datetime을 저장합니다 자정부터. (각각 약 3.33 밀리 초) –

+0

정확함. 끝나는 .003, .007 또는 .000 –

+0

감사! 나는 datetime이 1ms의 정확도를 가지고 있기 때문에 1ms로 정확하다고 가정했다. – Odrade