如何在 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 中指出的那样,我们可以使用 .Add
和 OleDbType.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 数据库中插入以毫秒为单位的日期时间?的主要内容,如果未能解决你的问题,请参考以下文章