ExecuteNonQuery 命令中缺少参数,在 VB.NET 和 Access 中使用

Posted

技术标签:

【中文标题】ExecuteNonQuery 命令中缺少参数,在 VB.NET 和 Access 中使用【英文标题】:Parameter missing in ExecuteNonQuery command, using in VB.NET and Access 【发布时间】:2012-11-23 20:06:33 【问题描述】:

我在 Access 2007 中有一个非常简单的数据库,我正在使用 VB 2010 连接它。有两个表,MenuItems 和 Orders,Orders.orderDate 的类型为“Date”。

我正在我的一种 VB 表单中运行以下代码(连接字符串和其他一切都很好):

  sql = "SELECT OrderDate, MenuItem FROM MenuItems, Orders WHERE Orders.itemID = MenuItem.ID AND Orders.orderDate BETWEEN '" + fromDate + "' AND '" + toDate + "'"
  Dim cmd As New OleDb.OleDbCommand(sql, con)
  Dim count As Integer = cmd.ExecuteNonQuery()

但我收到一个错误:

System.Data.OleDb.OleDbException (0x80040E10): value wan't given for one or more of the required parameters

似乎什么都没有。我对另一个查询使用了相同的代码,除了 sql 不同。但我认为我的 sql 足够简单。这是在一个实例中生成的 sql(我已经仔细检查过,所有表名和列名都是正确的):

SELECT OrderDate, MenuItem From MenuItems, Orders WHERE Orders.itemID = MenuItem.ID AND Orders.orderDate BETWEEN '11/21/2012' AND '11/24/2012'

【问题讨论】:

MS Access 中的日期分隔符是 # 注意日期的语言环境问题。 你的意思是它应该是 SELECT OrderDate, MenuItem From MenuItems, Orders WHERE Orders.itemID = MenuItem.ID AND Orders.orderDate BETWEEN #11/21/2012# AND #11/24/2012# ?我试过了,没有区别。 另外,select 不是非查询,它不返回整数。它返回一个记录集。 您是否尝试过使用参数而不是字符串连接?我想这两个日期值不太对劲。 【参考方案1】:

您应该使用参数化查询至少有两个原因。

    您不必担心日期(和其他)文字和语言环境问题。

    您不必担心 SQL 注入攻击,即有人在文本框中输入恶意代码,从而将 SQL 语句变为有害语句。

将你的陈述改为

sql = "SELECT Orders.OrderDate, MenuItems.MenuItem " & _
    "FROM MenuItems INNER JOIN Orders ON MenuItems.ID = Orders.itemID " & _
    "WHERE Orders.orderDate BETWEEN ? AND ?"

然后像这样执行命令

Dim fromDate, toDate As DateTime

fromDate = DateTime.Parse(fromDateTextBox.Text)
toDate = DateTime.Parse(toDateTextBox.Text)

Dim dataset As New DataSet()
Using conn As New OleDbConnection(connectionString)
    Using adapter As New OleDbDataAdapter()
        Dim cmd As New OleDbCommand(sql, conn)
        cmd.Parameters.Add("?", fromDate)
        cmd.Parameters.Add("?", toDate)
        adapter.SelectCommand =  cmd
        adapter.Fill(dataset)
    End Using
End Using

【讨论】:

好的,谢谢您的建议 - 我会这样做的。但是在这种情况下,fromDatetoDate 可以直接从表单的日期字段中取出吗?还是需要先格式化? 它们必须是 DateTime 对象。您可以使用DateTime.ParseDateTime.TryParse 进行转换,甚至可以使用VB 特定的CDate 函数。请注意,VB 为System.DateTime 结构提供了别名Date 还要注意术语“格式化”仅适用于字符串。将格式为DateTime 的日期字符串转换为无格式日期。 DateTime 将日期保留为 Double 数字,表示自参考日期以来的天数。数字的小数部分代表时间。【参考方案2】:

嗯,ExecuteNonQuery 方法用于更改数据的语句,即。 DELETE / UPDATE /INSERT,返回值是受该语句影响的行数。 由于您使用的是 Select 语句,因此您应该使用 oledbDataAdapter 和 Fil DataSet 来使用。

Dim conn As New OleDbConnection(con)
Dim adapter As New OleDbDataAdapter()
sql = "SELECT OrderDate, MenuItem FROM MenuItems, Orders WHERE Orders.itemID = MenuItem.ID AND Orders.orderDate BETWEEN '" + fromDate + "' AND '" + toDate + "'"
adapter.SelectCommand = new OleDbCommand(sql, con)
adapter.Fill(dataset)
Return dataset

【讨论】:

我按照建议将它从非查询更改为命令,但我得到了同样的错误。【参考方案3】:

问题是表格拼写错误。 (MenuItem而不是MenuItems),但它没有解决问题,我仍然得到一个错误。结果是数据库和用作查询参数的日期选择器值之间的匹配格式存在问题。

所以我确保我以短日期格式保存到数据库中:

sql = "INSERT INTO Orders(itemID, OrderDate) VALUES('" + ListBox1.SelectedValue.ToString() + "','" + FormatDateTime(OrderDate.Value, DateFormat.ShortDate) + "')"

【讨论】:

以上是关于ExecuteNonQuery 命令中缺少参数,在 VB.NET 和 Access 中使用的主要内容,如果未能解决你的问题,请参考以下文章

OracleCommand 命令,ExecuteNonQuery 问题

C# 中的事务和 ExecuteNonQuery 错误

对 ExecuteNonQuery 的 Postgres 函数(通过 npgsql)调用返回 -1 作为受影响行的结果

sql查询之ExecuteNonQuery

ADO.NET 中参数化 SQL 命令的最终形式

Sqoop命令 - 缺少选项的参数:merge-key