如何在 Access 数据库中插入以毫秒为单位的日期时间?

Posted

技术标签:

【中文标题】如何在 Access 数据库中插入以毫秒为单位的日期时间?【英文标题】:How to insert datetime with milliseconds into Access database? 【发布时间】:2015-03-23 06:07:00 【问题描述】:

我正在尝试使用 C# 将日期 + 时间插入 Access 数据库。时间字符串中包含毫秒,例如:

"2015-03-23 11:22:33.123"`

这是我的代码:

string strName = "somestring";
string strDate = "2015-03-23 11:22:33.123"

sql = @"insert into table_name  ([name], [date]) values (@Name, @Date)";

using (OleDbCommand command = new OleDbCommand(sql))

    command.Connection = openCon;
    command.Parameters.AddWithValue("@Name", strName);
    command.Parameters.AddWithValue("@Date", strDate ); // <-- error here          
    openCon.Open();
    recordsAffected = command.ExecuteNonQuery();
    openCon.Close();

ExcuteNonQuery() 出现错误;如果我删除日期时间字符串,则代码有效。

那么如何在 Access 数据库中插入以毫秒为单位的日期时间呢?

【问题讨论】:

该列的表中的数据类型是什么? 这是默认的日期/时间类型。 错误信息是什么究竟 它不适用于 AddWithValue,但它适用于 Add。看看我的正确答案。 【参考方案1】:

您正在混淆 DateTime 和 String。始终将 DateTime 用于日期/时间值或尽早转换为 DateTime。 因此:

string strDate = "2015-03-23 11:22:33.123";
DateTime datDate = DateTime.Parse(strDate);
// ...
//    command.Parameters.AddWithValue("@Date", datDate ); // <-- error here 

command.Parameters.Add("@Date",OleDbType.Date);
command.Parameters[0].Value = datDate;                    // <-- no error

请注意,尽管 Access 会正确存储该值,但它或 VBA 不会显示毫秒,而是会进行 4/5 舍入到秒。当然,如果您只从 C# 应用程序中读取这些值,这并不重要。

当插入到我的毫秒应用程序中时,该值将正确插入,如下所示:

DateTimeMs          SortValue       DateFull                CDouble             RoundSecSQL         MsecSQL MsecVBA SecondDec SecondStd
23-03-2015 11:22:33 60438568953123  23-03-2015 11:22:33.123 42086,4739944792    42086,4739930556    123     123     33,123    33
23-03-2015 11:45:31 60438570330707  23-03-2015 11:45:30.707 42086,4899387384    42086,4899305556    707     707     30,707    31

【讨论】:

re: "no error here" - 实际上是的,当调用.ExecuteNonQuery() 时,这将为 OleDbCommand 产生错误。详情请见my answer。 真神。那是空气代码,我通常使用 DataTableAdapters,所以我不应该聪明地使用 AddWithValue。但是,使用 Add 有效。请参阅我的更正答案。【参考方案2】:

访问“日期/时间”字段类型的标称分辨率为一秒。也就是说,当日期/时间值显示在 Access 中时,formatted 使用预定义或自定义格式,或使用 DateAdd 或 DatePart 等函数进行操作,我们可以指定的最小时间单位是 第二个

在 .NET 中使用 OLEDB

当通过System.Data.OleDb 对Access 数据库使用.AddWithValue 时,日期/时间字段的DateTime 参数不得具有毫秒值,否则插入/更新将失败。也就是说,

DateTime dt = Convert.ToDateTime("2015-03-23 11:22:33.123");
cmd.Parameters.AddWithValue("?", dt);
cmd.ExecuteNonQuery();

会失败

条件表达式中的数据类型不匹配。

但是,正如 Gustav 在 his answer 中指出的那样,我们可以使用 .AddOleDbType.Date 添加包含毫秒的 DateTime 参数,

DateTime dt = Convert.ToDateTime("2015-03-23 11:22:33.123");
cmd.Parameters.Add("?", OleDbType.Date).Value = dt;
cmd.ExecuteNonQuery();

并且该值将原封不动地存储在访问日期/时间字段中。我们可以通过检索存储的值并检查它来验证这一点

cmd.CommandText = "SELECT [date] FROM table_name WHERE ID = 13";
DateTime rtn = Convert.ToDateTime(cmd.ExecuteScalar());
Console.WriteLine(rtn.Millisecond);

...打印“123”,表明毫秒部分是返回值的一部分。

诀窍在于 Access 本身并没有为我们提供有效处理这些日期/时间值的毫秒部分的工具。在 Access/VBA 中执行此操作需要一些额外的编码,如另一个站点 here 上的文章中所述。

(当然,如果您只对将值拉回 .NET 应用程序感兴趣,那么您可以使用上面的代码 sn-p。)

在 .NET 中使用 ODBC

System.Data.Odbc 使用相同的方法会产生略微不同的结果。 Access ODBC 驱动程序将接受具有毫秒值的 DateTime 参数 .Add.AddWithValue 但它不会存储毫秒。

此外,如果我们尝试检索使用 OLEDB 存储的以毫秒为单位的日期/时间值,则 Access ODBC 驱动程序删除毫秒。也就是说,如果我们尝试使用下面的 ODBC 代码来检索我们通过上面的 OLEDB 示例存储的“毫秒值”...

// cmd is now an OdbcCommand object
cmd.CommandText = "SELECT [date] FROM table_name WHERE ID = 13";
DateTime rtn = Convert.ToDateTime(cmd.ExecuteScalar());
Console.WriteLine(rtn.Millisecond);

...它打印“0”,即使我们可以通过以下操作验证 Double 值的毫秒部分是否已存储在数据库中

cmd.CommandText = "SELECT CDbl([date]) AS foo FROM table_name WHERE ID = 13";
Double rtn = Convert.ToDouble(cmd.ExecuteScalar());
Console.WriteLine(rtn);

并检查 Double 值的小数部分。

替代品

如果您想保持在日期/时间字段类型的标称 1 秒分辨率范围内,您可以...

将值四舍五入到最接近的秒数:

DateTime dt = Convert.ToDateTime("2015-03-23 11:22:33.123");
if (dt.Millisecond >= 500)

    dt = dt.AddSeconds(1);

dt = dt.AddMilliseconds(-dt.Millisecond);
cmd.Parameters.AddWithValue("?", dt);
cmd.ExecuteNonQuery();

或者,如果您想保留毫秒,那么您要么必须将截断(未四舍五入)的日期/时间和毫秒存储在单独的字段中,或者可能只是将原始字符串值存储在文本字段中。

【讨论】:

Access 的设计真的很混乱!如果它确实在 Date/Time 字段中存储毫秒,为什么它不能接受 DateTime 包含毫秒?无论如何,如果没有更好的答案出现,我会接受这个答案:-) Access 可以并且将存储毫秒 - 只是不是本地的,这就是产生混淆的地方。您必须在 VBA 中使用自定义代码。但是,..Net 处理毫秒,并且使用 Add 而不是 AddWithValue 您可以存储毫秒。请参阅我的更正答案。 @Gustav 感谢您的解释!我已经更新了我的答案。 感谢您的总结,戈德。我不知道完全忽略毫秒的 ODBC 行为。【参考方案3】:

你必须这样尝试:

command.Parameters.AddWithValue("@Date", GetDateWithMilliseconds(strDate));

private DateTime GetDateWithoutMilliseconds(DateTime d)

    command new DateTime(d.Year, d.Month, d.Day, d.Hour, d.Minute, d.Second,d.Milliseconds);

您收到错误的原因是,当您通过 AddWithValue 使用 OleDbType 时,它​​是 DBTimeStamp,但 Access 需要 OleDbType.Date。详情请查看MSDN

或者你可以这样尝试:

command.Parameters.Add("@Date", OleDbType.Date).Value = strDate;

【讨论】:

我是否需要使用 Convert.ToDateTime(strDate) 将 string strDate 转换为 DateTime d @TRX:- 如果可能,那就去做吧! 你不应该使用字符串作为日期/时间。 @Gustav:- 这不是问题,顺便说一句,OP 已要求将其从 String 更改为 Date 我建议继续进行! :) 好吧,你是对的,但是“可能”这个词让我印象深刻。【参考方案4】:

试试这个

string strDate = "2015-03-23 11:22:33"

【讨论】:

你的意思是 Access 不能存储日期/时间类型的毫秒数吗? 无访问以日期/时间类型存储毫秒,但毫秒不应为十进制格式。应该是这样的字符串 strDate = "2015-03-23 11:22:33" 这是不正确的。这不是 VBA,但 .Net 和日期/时间永远不应该是字符串。没有例外。 @TRX 您是否尝试过使用以下行字符串 strDate = "2015-03-23 11:22:33" @IJAJMULANI "2015-03-23 11:22:33" 没有毫秒,不是吗? ://

以上是关于如何在 Access 数据库中插入以毫秒为单位的日期时间?的主要内容,如果未能解决你的问题,请参考以下文章

以毫秒为单位的日期时间选择器

使用 PHP 将时间戳以毫秒为单位插入 Postgres 表

MFC 以毫秒为单位的测量功能

BigQuery 没有以毫秒为单位处理带有分区列的时间戳

如何在 Ruby 中以毫秒为单位计时?

如何以毫秒为单位显示 ssms 的执行时间?