参数化查询无效(vb.net,OleDb)

时间:2015-07-08 15:36:16

标签: vb.net

我已经在我的表单中运行了查询并返回进行一般清理并参数化查询,并且遇到一个使用LIKE关键字和通配符(%)的查询时遇到问题。查询从Access数据库获取信息或作用于Access数据库。请注意,SQL注入攻击不是问题,因为运行此表单的位置与外部世界没有连接(none,zero,zip)。所以SQL注入巨魔请克制。

另外请注意,我不是一个经验丰富的VB'er或.NET'er,所以我可以根据搜索StackOverFlow做到这一点(已经证明在很多场合都非常有用,谢谢大家!)

  1. Me.cmboAssemblyNum.Text的值格式为X31-D104518-1-00101 - **。
  2. 开头总会有一个字母字符
  3. 最后一个字符的范围从双星号到2个字母字符(它是部件/图纸的修订版)
    • 我知道双星号是一个糟糕的选择,但这是我必须使用的,它无法改变
  4. 使用LIKE和%过滤的字段将包含以下内容:
    • 已添加至X31-D104518-1-00101 - **
    • 从X31-D104518-1-00101删除 - **
  5. 查看它有点难看,但原始的,有效的查询文本如下。请注意,我为可读性而格式化,但它可以正常工作,因此任何错别字都不是问题。

    "SELECT HistoryID, InventoryID, SerialNumber, QuantityChange, TransactionAction, Notes, TransactionDate, TransactionTime
    FROM InventoryHistory
    WHERE ((((InventoryHistory.TransactionAction) Like '%" + Me.cmboAssemblyNum.Text + "')
    AND ((InventoryHistory.Location) = 'INVENTORY'))
    OR (((InventoryHistory.SerialNumber) = '" + Me.cmboAssemblyNum.Text + "') AND ((InventoryHistory.TransactionAction) = 'Assembly is complete'))
    OR ((InventoryHistory.Location) = '" + Me.cmboAssemblyNum.Text + "'))"
    

    我使用@cmboAssemblyNum以下列方式对查询进行了参数化,但它不起作用。我没有得到任何错误,但查询没有返回预期的值。我再次编写了可读性,我在代码中所做的就是用@cmboAssemblyNum替换“+ Me.cmboAssemblyNum.Text +”。

    我也尝试了以下有或没有单引号,例如: '%@ cmboAssemblyNum'。

    "SELECT HistoryID, InventoryID, SerialNumber, QuantityChange, TransactionAction, Notes, TransactionDate, TransactionTime
    FROM InventoryHistory
    WHERE (((InventoryHistory.TransactionAction Like %@cmboAssemblyNum)
    AND ((InventoryHistory.Location) = 'INVENTORY'))
    OR (((InventoryHistory.SerialNumber) = @cmboAssemblyNum)
    AND ((InventoryHistory.TransactionAction) = 'Assembly is complete'))
    OR ((InventoryHistory.Location) = @cmboAssemblyNum))"
    

    执行此查询的完整代码是。

    Dim ds As New DataSet
    Dim da As New OleDb.OleDbDataAdapter
    
    'If an assembly has been started but not completed, get list of items already added
    strSQL = "SELECT HistoryID, InventoryID, SerialNumber, QuantityChange, TransactionAction, Notes, TransactionDate, TransactionTime " & _
    "FROM InventoryHistory " & _
    "WHERE (((InventoryHistory.TransactionAction Like %@cmboAssemblyNum) AND ((InventoryHistory.Location) = 'INVENTORY')) OR (((InventoryHistory.SerialNumber) = @cmboAssemblyNum) AND ((InventoryHistory.TransactionAction) = 'Assembly is complete')) OR ((InventoryHistory.Location) = @cmboAssemblyNum))"
    
    Try
       'run strSQL statement fills tbl_ExistingTransactions with resulting dataset
       da.SelectCommand = New OleDb.OleDbCommand(strSQL, Conn_Backend)
       da.SelectCommand.Parameters.AddWithValue("@cmboAssemblyNum", Me.cmboAssemblyNum.Text)
       da.Fill(ds)
       tbl_ExistingTransactions = ds.Tables(0)
    
    Catch ex As Exception
        Me.txtStatus.Text = "Caught exception when running strSQL the first time in UpdateDataGridView"
    
    End Try
    

    感谢任何帮助或指导。我已经搜索过StackOverFlow以及其他网站,并且找不到迄今为止有用的任何内容。

    我不相信我可以包括表格的样本,但如果我能够,我会这样做。

3 个答案:

答案 0 :(得分:3)

Try with the % wildcard character in the parameter value, instead of in the SQL:

Dim ds As New DataSet
Dim da As New OleDb.OleDbDataAdapter

'If an assembly has been started but not completed, get list of items already added
strSQL = "SELECT HistoryID, InventoryID, SerialNumber, QuantityChange, TransactionAction, Notes, TransactionDate, TransactionTime " & _
"FROM InventoryHistory " & _
"WHERE (((InventoryHistory.TransactionAction Like @cmboAssemblyNum) AND ((InventoryHistory.Location) = 'INVENTORY')) OR (((InventoryHistory.SerialNumber) = @cmboAssemblyNum) AND ((InventoryHistory.TransactionAction) = 'Assembly is complete')) OR ((InventoryHistory.Location) = @cmboAssemblyNum))"

Try
   'run strSQL statement fills tbl_ExistingTransactions with resulting dataset
   da.SelectCommand = New OleDb.OleDbCommand(strSQL, Conn_Backend)
   da.SelectCommand.Parameters.AddWithValue("@cmboAssemblyNum", "%" & Me.cmboAssemblyNum.Text)
   da.Fill(ds)
   tbl_ExistingTransactions = ds.Tables(0)

Catch ex As Exception
    Me.txtStatus.Text = "Caught exception when running strSQL the first time in UpdateDataGridView"

End Try

答案 1 :(得分:0)

Try this:

WHERE (((InventoryHistory.TransactionAction Like '%' + @cmboAssemblyNum)

答案 2 :(得分:0)

我想我已将其整理出来,但我无法解释为什么会有效。我创建了一个INI文件,并在INI中包含以下内容,这是我最初在我的代码中尝试的内容(即用@cmboAssemblyNum替换“+ Me.cmboAssemblyNum.Text +”)。我使用GetPrivateProfileString读取INI文件并将值存储在字符串中。

sql_tblExistingTransactions="SELECT HistoryID, InventoryID, SerialNumber, QuantityChange, TransactionAction, Notes, TransactionDate, TransactionTime FROM InventoryHistory WHERE ((((InventoryHistory.TransactionAction) Like '%@cmboAssemblyNum.Text') AND ((InventoryHistory.Location) = 'INVENTORY')) OR (((InventoryHistory.SerialNumber) = @cmboAssemblyNum.Text) AND ((InventoryHistory.TransactionAction) = 'Assembly is complete')) OR ((InventoryHistory.Location) = @cmboAssemblyNum.Text))"

然后我在我的问题中按原样运行了我的代码:

   da.SelectCommand = New OleDb.OleDbCommand(strSQL, Conn_Backend)
   da.SelectCommand.Parameters.AddWithValue("@cmboAssemblyNum", Me.cmboAssemblyNum.Text)
   da.Fill(ds)
   tbl_ExistingTransactions = ds.Tables(0)

它按预期工作。

我们仍然使用INI文件进行查询,但在外部进行开发以避免在进行更新时出现服务问题,以便解决问题。

任何人都可以想出为什么在从INI文件中读取字符串时它会起作用但在代码中使用内联SQL语句时不起作用?

我会尝试其他一些事情,但我认为我不会理清为什么这样做。