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

How to insert datetime with milliseconds into Access database?

我正在尝试使用 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 数据库中?

你必须这样尝试:

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;

试试这个

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

您混淆了 DateTime 和 String。始终对 date/time 值使用 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

Access "Date/Time" 字段类型的标称分辨率为一秒。即Access中显示Date/Time个值时,formatted using pre-defined or custom formats, or manipulated with functions like DateAdd or DatePart,我们可以指定的最小时间单位是.

在 .NET 中使用 OLEDB

当通过 System.Data.OleDb 对 Access 数据库使用 .AddWithValue 时,Date/Time 字段的 DateTime 参数不能有毫秒值或 insert/update 将失败。也就是说,

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

将失败

Data type mismatch in criteria expression.

然而,正如 Gustav 在 中指出的那样,我们可以使用 .AddOleDbType.Date 来添加一个包含毫秒的 DateTime 参数,

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

并且该值将原封不动地存储在 Access Date/Time 字段中。我们可以通过检索存储的值并检查它来验证这一点

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

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

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

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

在 .NET 中使用 ODBC

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

此外,如果我们尝试检索使用 OLEDB 存储的 Date/Time 毫秒值,A​​ccess ODBC 驱动程序 会删除 毫秒。也就是说,如果我们尝试使用以下 ODBC 代码来检索我们通过上面的 OLEDB 示例存储的 "millisecond value" ...

// 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 值的小数部分。

备选方案

如果您想保持在 Date/Time 字段类型的标称 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();

或者,如果您想保留毫秒数,那么您要么必须将截断的(未舍入的)Date/Time 和毫秒数存储在单独的字段中,要么只将原始字符串值存储在文本中场.