如何将以毫秒为单位的日期时间插入到 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 在 中指出的那样,我们可以使用 .Add
和 OleDbType.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 毫秒值,Access 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 和毫秒数存储在单独的字段中,要么只将原始字符串值存储在文本中场.
我正在尝试使用 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 在 .Add
和 OleDbType.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 毫秒值,Access 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 和毫秒数存储在单独的字段中,要么只将原始字符串值存储在文本中场.