C# 使用ODBC将日期时间值插入Access数据库

C# 使用ODBC将日期时间值插入Access数据库,c#,vb.net,datetime,ms-access,odbc,C#,Vb.net,Datetime,Ms Access,Odbc,对SQL来说相当陌生。我们的应用程序以较旧的Access(2007年以前)数据库为目标。我的表有许多不同类型的字段,如SMALLINT,VARCHAR,DATETIME 在以下示例中: “研究”类型为SMALLINT “日期”的类型为DATETIME “患者”的类型为VARCHAR 我正在尝试使用SQL语句将新记录插入MyTable: OdbcConnection connection = new OdbcConnection(connectionString); OdbcCommand c

对SQL来说相当陌生。我们的应用程序以较旧的Access(2007年以前)数据库为目标。我的表有许多不同类型的字段,如
SMALLINT
VARCHAR
DATETIME

在以下示例中:

  • “研究”类型为
    SMALLINT
  • “日期”的类型为
    DATETIME
  • “患者”的类型为
    VARCHAR
我正在尝试使用SQL语句将新记录插入MyTable:

OdbcConnection connection = new OdbcConnection(connectionString);
OdbcCommand command = connection.CreateCommand();
command.CommandType = CommandType.Text;
command.CommandText = "INSERT INTO Studies (Study, Date, Patient) VALUES (1411,#2021-20-23#,'Fred');";
command.ExecuteNonQuery();
每次
ExecuteNonQuery
抛出异常时: {“INSERT INTO语句中出现错误[42000][Microsoft][ODBC Microsoft Access驱动程序]语法错误。”}

修改
插入
并正确插入记录:

"INSERT INTO Studies (Study, Patient) VALUES (1411,'Fred');"
我尝试了各种方式格式化日期/时间变量:

  • #年月日#
  • #yyyy-mm ddThh:mm:ss#
  • #yyyy mm dd hh:mm:ss#
  • “yyyy-mm-dd” (随着时间的推移)
  • 年月日 (随着时间的推移)
…这些似乎都不起作用


如何使用ODBC将日期时间值插入Access数据库?

非常感谢评论员,特别是@June7和@madreflection,他们捕捉到了语法中的一些基本错误:

  • Date
    是Access中的保留关键字。如果您的字段(不幸地)被称为“日期”,则需要引用它。使用
    [Date]
    ,而不是
    日期
  • 日期时间格式不正确。它应该是
    #yyyy-MM-dd#
    #yyy-MM-dd HH:MM:ss#
    。请注意,月份的错误为“mm”而不是“mm”,小时的错误为“hh”而不是“hh”
  • 正如@Jimi所指出的,虽然您可以手动构建
    INSERT-INTO
    语句,但更好的方法是使用IDbCommand.Parameters。这简化了生成命令时的格式设置问题

嗯,通常很多人都会插嘴说嘿您应该使用参数

他们是对的——但有一个大的额外功能?所有类型转换都是自动完成的。那么,代替容易出错的字符串?你会得到这样的结果:

    Using cmdSQL As New OdbcCommand("INSERT INTO Studies (Study, [Date], Patient) VALUES (@Study, @Date, @Patient",
                                     New OdbcConnection(connectionString))

        cmdSQL.Parameters.Add("@Study", OdbcType.Int).Value = 1411
        cmdSQL.Parameters.Add("@Date", OdbcType.Date).Value = "2021-20-23"
        cmdSQL.Parameters.Add("@patient", OdbcType.NVarChar).Value = "Fred"
        cmdSQL.Connection.Open()
        cmdSQL.ExecuteNonQuery()

        cmdSQL.Dispose()

    End Using
现在,你的例子当然只是一个例子。但是,如果您有强类型变量,则可以执行以下操作:

cmdSQL.Parameters.Add("@Study", OdbcType.Int).Value = intStudy
cmdSQL.Parameters.Add("@Date", OdbcType.Date).Value = dtInvoiceDate
cmdSQL.Parameters.Add("@DateT", OdbcType.DateTime).Value = dtInvoiceTime
cmdSQL.Parameters.Add("@Customer", OdbcType.NVarChar).Value = strCompanyName
因此,在创建上述内容时,您可以按ctrl-d复制第一行,这样您就不需要键入太多内容。您只需编辑并更改参数值。而且您永远不必使用引号、无引号或日期分隔符(假设您将变量声明为date或datetime)

我发现告别混乱的字符串连接?嗯,这不仅是sql注入安全的,而且处理起来也不那么混乱。使用干净的变量,进行强大的数据类型检查,不必考虑或记住关于引号、无引号或某种日期格式的规则。它只是干净的代码,只需赋值美国

因此,这是一个稍微多一点的代码,但实际上您不必键入代码(使用ctrl-d复制第一个参数行,然后您只需在代码中四处移动并替换@parm和.value)。您可以对表单数据输入进行如下操作:

cmdSQL.Parameters.Add("@Study", OdbcType.Int).Value = cboDrop.dataValue
cmdSQL.Parameters.Add("@Date", OdbcType.Date).Value = InvoiceDate.text
cmdSQL.Parameters.Add("@DateT", OdbcType.DateTime).Value = InvoiceTime.Text
cmdSQL.Parameters.Add("@Customer", OdbcType.NVarChar).Value = CompanyName.Text

因此,一旦您引入控件,那么如果您使用字符串,您就真的会遇到麻烦-因为您不能只在控件中使用字符串,因此字符串sql方法会变得更糟糕,更难编写。

使用命令参数传递值。日期是Access中的保留字。如果将它括在[]-
[Date]中会发生什么
?或者在日期结构中使用/而不是-。我觉得有必要指出,
2021-20-23
不是一个有效的日期,所以即使你引用了
date
,正如6月7日所说,它最终肯定会抱怨,如果不是下一个。@June7:哦,好地方……我试过
[date]
这似乎没有帮助,但会尝试/now。哎呀,我在这里犯了几个错误,反映了我对SQL、ODBC和Access的经验不足。June7、madreflection和Jimi都没有问题。我的格式应该是“#yyyy-MM-dd HH:MM:ss”#(我使用的是“#yyyy-MM-ddThh:MM:ss#”,有两个错误),“Date”字段需要用[]方括号分隔,最后我应该像Jimi指出的那样使用命令参数。谢谢大家!术语挑剔:不分隔,带引号。即使既不使用引号也不使用撇号字符,从技术上讲它仍然是“引号”.Microsoft在Access和SQL Server中都使用方括号进行引号。SQL Server还允许在启用正确会话设置的情况下使用引号字符(
SET QUOTED\u IDENTIFIER ON
)。我不知道是否需要访问。@madreflection:好的,今晚我学到了另一件事……谢谢!但我必须承认,引用不会从舌头上溜走。这可能需要一些时间来适应。术语很重要。定界是关于分隔事物,就像你可能用逗号一样。引用是关于隔离和包含不应该包含的事物不要被解读,比如一个不应该被视为关键词的名字,或者其他人说你不想被当作你的话。