我正在尝试使用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()
收到错误;如果我删除日期时间字符串,那么代码可以正常工作。
那么如何将datetime和毫秒插入Access数据库?
答案 0 :(得分:3)
您正在混合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#应用程序中读取这些值,那么这一点并不重要。
当插入我的Millisecond应用程序时,可以正确插入该值:
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
答案 1 :(得分:2)
访问&#34;日期/时间&#34;字段类型的标称分辨率为一秒。也就是说,当在Access中显示日期/时间值时,formatted使用预定义或自定义格式,或使用DateAdd或DatePart等函数进行操作,我们可以使用最小的时间单位指定是第二个。
将OLED与.NET结合使用
通过.AddWithValue
对Access数据库使用System.Data.OleDb
时,日期/时间字段的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);
...打印&#34; 123&#34;,表明毫秒组件是返回值的一部分。
诀窍在于Access本身并没有为我们提供有效使用这些日期/时间值的毫秒部分的工具。要在Access / VBA中执行此操作,需要一些额外的编码,如另一个网站here上的文章所述。
(当然,如果您只想将值拉回到.NET应用程序中,那么您可以使用上面的代码片段。)
将ODBC与.NET一起使用
对System.Data.Odbc
使用相同的方法会产生稍微不同的结果。 Access ODBC驱动程序将为DateTime
和.Add
接受带有毫秒值的.AddWithValue
参数,但 NOT 将存储毫秒数。
此外,如果我们尝试检索使用OLEDB存储的毫秒数的日期/时间值,则Access ODBC驱动程序将删除毫秒。也就是说,如果我们尝试使用以下ODBC代码来检索&#34;毫秒值&#34;我们通过上面的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);
...它打印&#34; 0&#34;,即使我们可以通过
验证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();
或者,如果你想保持毫秒,那么你必须将截断的(不是舍入的)日期/时间和毫秒存储在单独的字段中,或者只是将原始字符串值存储在文本字段中。
答案 2 :(得分:1)
你必须尝试这样:
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;
答案 3 :(得分:-1)
尝试使用此
string strDate = "2015-03-23 11:22:33"