Unerwünschte Rundung von DateTime in SQL Server
Ich lief in etwas, das scheint seltsam. SQL Server scheint zu sein, die Rundung einige DateTime
Werte unangemessen, wenn ich speichern Sie Sie auf datetime
Spalten. Ich vermute, ich bin etwas fehlt, aber ich kann nicht finden es. Ich bin mit diesem test gegen den SQL Server 2008 verwenden .NET 4.0. Folgendes sollte illustrieren das Problem:
Habe ich eine Tabelle in SQL Server, den so genannten Zeitstempel. Es hat zwei Spalten:
id - bigint, Identität, PK
timestamp - datetime -
Ich auch einen einfachen test, der das folgende tut:
- Wird die aktuelle Zeit, das abschneiden der Wert in Millisekunden-Präzision
- Gespeichert, die abgeschnittene Zeit für
Timestamps
- Abgerufen datetime " - Wert aus der DB und im Vergleich zum original (gekürzt) DateTime-Objekt.
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();
}
}
}
Obwohl ich erwarte, dass der abgeschnittene Wert entspricht dem Wert, der zurückgegeben wird wieder von der DB, dass ist nicht immer der Fall. Hier einige Beispiel-Ausgabe:
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()
sieht wie folgt aus:
public static DateTime TruncateToMilliseconds(this DateTime t)
{
return new DateTime(t.Year, t.Month, t.Day, t.Hour, t.Minute, t.Second, t.Millisecond);
}
Was gibt? Ist das wirklich unangemessen Rundung, oder bin ich einer falschen Annahme hier?
- Anscheinend ist der SQL-standard ist die Rundung (nicht abschneiden)... was ist horror, denn es führt zu ungewollten datetimes in die Zukunft. Auch wenn der gleiche server fragt dann "alles, was nicht in der Zukunft", die nur bestimmt und nur eingefügt datetime (die per definition würden wir nicht berücksichtigen, werden in der Zukunft) können ausgeschlossen werden.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Datetime nur genau auf 3ms. Deshalb werden Runde auf das nächste Vielfache von 3ms. Um diese zu überwinden, schauen Sie auf der datetime2. Beachten Sie, dass dies für SQL2008+ nur
EDIT: es ist nicht ganz nur auf 3ms. Es ist gerundet-Schritten von .000, .003, oder .007 Sekunden