【问题标题】:Building SQL query for search string为搜索字符串构建 SQL 查询
【发布时间】:2016-05-10 02:01:57
【问题描述】:

我在创建用于在数据网格视图中显示项目的搜索查询时遇到了一些问题,我得到的错误是“索引超出范围。必须是非负数并且小于集合的大小。 参数名称:索引"

下面是我的代码:

Try
    connect()
    Dim sql = "SELECT pcb, component, hour, faultcode, line FROM [sqlcnvfaultentry] WHERE "

    If CheckBox_pcb.Checked Then
        Sql = Sql & " and pcb = @pcb "
        cmd.Parameters.AddWithValue("@pcb", ComboBox_pcb.Text)
    End If

    If CheckBox_part.Checked Then
        Sql = Sql & " and component = @component "
        cmd.Parameters.AddWithValue("@component", ComboBox_part.Text)
    End If

    If CheckBox_hour.Checked Then
        Sql = Sql & " and hour = @hour "
        cmd.Parameters.AddWithValue("@hour", ComboBox_hour.Text)
    End If

    If CheckBox_fault.Checked Then
        Sql = Sql & " and faultcode = @faultcode "
        cmd.Parameters.AddWithValue("@faultcode", ComboBox_fault.Text)
    End If

    If CheckBox_line.Checked Then
        Sql = Sql & " and line = @line "
        cmd.Parameters.AddWithValue("@line", ComboBox_line.Text)
    End If

    Dim adapter = New SqlDataAdapter(cmd.CommandText, con.ConnectionString)
    Dim dt As New DataTable()

    cmd.CommandText = Sql
    adapter.Fill(dt)
    DataGridView_c1.DataSource = dt
    DataGridView_c1.Refresh()

    DataGridView_c1.Columns(0).HeaderText = "PCB:"
    DataGridView_c1.Columns(1).HeaderText = "Component:"
    DataGridView_c1.Columns(2).HeaderText = "Hour:"
    DataGridView_c1.Columns(3).HeaderText = "Fault Code:"
    DataGridView_c1.Columns(4).HeaderText = "Line:"

    disconnect()

Catch exp As Exception
    Throw exp
Finally

End Try

任何帮助都会很棒。

【问题讨论】:

  • 哪一行抛出异常?
  • 所有字符串连接都将在命令文本的末尾产生WHERE and blah = @blah。该语法在“where”和“and”之间无效。此外,在您已经从中创建了 SqlDataAdapter 之后,您正在设置 cmd 对象的 commandText
  • 我已更改“Where 1=1”的代码 - 但引发异常的行是 - DataGridView_c1.Columns(1).HeaderText = "Component:"
  • cmd.CommandText = Sql 行移动到Dim adapter = 位上方的一行。
  • 字符串连接会使您面临 SQL 注入和意外错误,无论它是否包含参数占位符。这不是参数化查询。如果你真的需要这样一个开放式查询,使用支持LINQ的ORM(例如EF,NH)并动态添加.Where(...)子句

标签: mysql vb.net visual-studio


【解决方案1】:

好吧,看起来您的 TSQL 永远不会有效。您开始使用值为SELECT... WHERE 的语句,然后开始向其附加所有以AND 开头的内容。为了解决这个问题,您可以将语句开头为SELECT... WHERE 1=1,然后当您开始将AND 语句附加到您的WHERE 子句时,您应该没问题。

也就是说,我不太喜欢这种用于构建 SQL 语句的方法,我更愿意看到一个存储过程。

现在,至于您的实际错误:由于您的 TSQL 语句无效,因此您的结果没有任何列,并且这部分代码...

DataGridView_c1.Columns(0).HeaderText = "PCB:"
DataGridView_c1.Columns(1).HeaderText = "Component:"
DataGridView_c1.Columns(2).HeaderText = "Hour:"
DataGridView_c1.Columns(3).HeaderText = "Fault Code:"
DataGridView_c1.Columns(4).HeaderText = "Line:"

...超出范围,因为您没有记录集,因为您的 SELECT 语句无效。

【讨论】:

  • 嗯,好吧,我明白了,所以我已将其更改为 WHERE 1=1 但仍有问题。
  • 在运行之前输出您的SELECT 语句,然后在您的 vb.net 代码之外针对您的数据库运行它。我的预感是你的 TSQL 仍然无效。
  • @LDMJoe,虽然你是对的,但你错过了一些东西。即使该语句被更正为具有有效的语法,在已经从它创建SqlDataAdapter 之后设置cmd 对象的commandText 仍然存在问题。基本上查询文本永远不会被执行。
  • @вʀaᴎᴅᴏƞвєнᴎєƞ 谢谢 - 我的 vb.net 不如我的 SQL 敏锐,所以一旦我发现 SQL 问题,我认为这是唯一的问题!
【解决方案2】:

在将 SqlCommand.CommandText 传递给 SqlDataAdapter 之后设置它不会更改存储在适配器中的文本,在创建适配器之前移动 SqlCommand.Commandtext 的设置似乎是一个很好的修复......

cmd.CommandText = Sql
Dim adapter = New SqlDataAdapter(cmd.CommandText, con.ConnectionString)
Dim dt As New DataTable()
adapter.Fill(dt)

但是,等等,你还是有问题。当您将字符串(作为 CommandText)传递给适配器构造函数时,它会使用该字符串在内部构建另一个 SqlCommand。此内部命令的参数集合为空。它对您的代码在外部创建的参数集合一无所知。
因此,真正的解决方法是直接使用您的代码准备的 SqlCommand 创建适配器。

cmd.CommandText = Sql
cmd.Connection = con

' Pass the SqlCommand, it will be used to be the SelectCommand of the adapter'
Dim adapter = New SqlDataAdapter(cmd)
Dim dt As New DataTable()
' Run the SelectCommand'
adapter.Fill(dt)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-07-24
    • 2021-08-26
    • 1970-01-01
    • 2013-06-10
    • 1970-01-01
    • 2015-02-15
    • 1970-01-01
    相关资源
    最近更新 更多