来自 cmets:my db field is a timestamp 和 I fix temp using a varchar instead a datetime or timestamp
TimeStamp 列与DateTime 列并不完全相同。根据Documentation:
MySQL 将 TIMESTAMP 值从当前时区转换为 UTC 进行存储,并从 UTC 转换回当前时区进行检索。 (这不会发生在其他类型,例如 DATETIME。)
这是您可能永远看不到的东西,即使是 MySQL WorkBench UI 也会将其转换回来。
小数秒
Fractional Seconds 的问题是另外一回事。将列定义为 DateTime 或 TimeStamp 时,默认情况下会删除小数秒,以便与旧版本兼容。
而不是将任何类型的Date 列定义为字符串/文本/varchar - 当然必须将其解析回来 - 您可以定义任一类型以保留小数秒。在 MySQL 5.6.4+ 中,您可以使用:DATETIME(n) 或 TIMESTAMP(n)(是的,那就是为什么括号会显示在 UI 下拉列表中)。其中n 是要存储的小数位数 (0-6)。对于 .NET,3 相当于毫秒。之后,WorkBench UI 也会显示毫秒数:
- StartDate 为
DateTime(0)(无小数)
- 上次更新时间为
TimeStamp(3)
- Foo 是
TimeStamp(6)
触发器
LastUpdated 列似乎最好由数据库管理,因此您不必通过代码来管理 - 或者 忘记 这样做!。使用默认值和Before_Update 触发器非常简单:
- 将列定义为
TIMESTAMP(3)
- 将
CURRENT_TIMESTAMP(3)指定为默认值
添加列LastUpdatedTIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '';
这将自动为添加到当前时间(UTC 等)的新项目设置 LastUpdated 值,以毫秒为单位(TIMESTAMP(6) 可能更好,但问题只关心毫秒)。请务必在默认中指定相同的位数。
然后,在更新每条记录时,不要手动传递DateTime.Now(或转换为字符串),而是添加一个触发器来为您更新列。在 MySql 工作台中:
CREATE DEFINER=`root`@`localhost` TRIGGER `test`.`demo_BEFORE_INSERT` BEFORE INSERT ON `demo` FOR EACH ROW
BEGIN
SET new.LastUpdated := now(3);
END
其中大部分是 UI 工具创建的样板。您只需输入:
SET new.LastUpdated := now(3);
对于这种类型的列,您可以在 BEFORE_INSERT 触发器上添加相同的内容来代替默认值。在 MySQL WorkBench 中,查看表定义时单击“触发器”选项卡 - 只需添加 SET 语句。
测试代码
这显示了从代码到数据库并返回的往返时间的小数毫秒,并显示触发器工作(使用上面显示的表格):
Dim Usql = "UPDATE Demo SET Foo = @p1 WHERE Id=5"
Dim Ssql = "SELECT Name, StartDate, Foo, LastUpdated FROM Demo WHERE Id=5"
Dim dtVar As DateTime = DateTime.Now
Console.WriteLine("DT ms in code var: {0}", dtVar.Millisecond)
Using dbcon = GetMySQLConnection()
dbcon.Open()
Using cmd As New MySqlCommand(Usql, dbcon)
cmd.Parameters.AddWithValue("@p1", dtVar)
cmd.ExecuteNonQuery()
End Using
Using cmd As New MySqlCommand(Ssql, dbcon)
Using rdr As MySqlDataReader = cmd.ExecuteReader
If rdr.HasRows Then
rdr.Read()
Dim tempDT = rdr.GetMySqlDateTime(1) ' DateTime(0)
Console.WriteLine("DT.MS from DB {0}", tempDT.Millisecond)
Dim mydt = rdr.GetMySqlDateTime(2) ' TimeStamp(6)
Console.WriteLine("Micro from DB {0} ", mydt.Microsecond)
' either get method retains the ms TimeStamp(3)
Dim lstupD = Convert.ToDateTime(rdr("lastUpdated"))
Console.WriteLine("MS from trigger {0}", lstupD.Millisecond)
End If
End Using
End Using
End Using
结果:
代码变量中的 DT ms:615
来自 DB 0 的 DT.MS
来自 DB 615413 的微型
触发 615 的 MS
定义为存储小数秒的列可以精确到微秒(滴答声)。请注意,更新 SQL 没有引用 LastUpdated 列,但它是由触发器更新的。如果您正在逐步调试并使用上述变量,则触发时间可能与其他变量有所不同,因为时间会随着您逐步进行而流逝。