使用参数为IN子句的SQL Server查询

杰米·蒂尔玛(Jamie Tilma)

我正在尝试使用该IN子句进行更新,但是我似乎无法使其正常工作。iArr创建了一个用逗号分隔的数字列表,理论上,一旦用方括号括起来,它应该进行更新,但是似乎不起作用。我不断收到错误消息

将nvarchar值'111111、222222、333333'转换为数据类型int时,转换失败。

知道如何解决这个问题吗?完整代码如下:

    Dim iArr As String
    iArr = ""
    For i As Integer = 0 To ufReview.InvoiceGrid.Rows.Count - 1
        iArr = iArr & ufReview.InvoiceGrid.Rows(i).Cells(0).Value & ", "
    Next i
    iArr = Left(iArr, Len(iArr) - 2)

    Dim SQL_Arr As String = _
            <SQL>
               UPDATE SCInv SET Inv_Transfer_Date = @UpdateCommand WHERE Inv_Num IN (@Array)
            </SQL>

    Dim cnt As New SqlConnection()
    Dim cmd As New SqlCommand()
    cnt.ConnectionString = "Data Source=SERVERNAME;Initial Catalog=CAT;User ID=USERID;Password=PASSWORD"
    Try
        cnt.Open()
        cmd.Connection = cnt
        cmd.CommandText = SQL_Arr
        cmd.Parameters.Clear()
        cmd.Parameters.AddWithValue("@UpdateCommand", UpdateCommand)
        cmd.Parameters.AddWithValue("@Array", iArr)
        Dim RACount As Integer = cmd.ExecuteNonQuery()
        MsgBox("The following Summary Numbers are now marked as " & UpdateFeedback & ": " & vbCrLf & iArr _
               & vbCrLf & vbCrLf & "(" & RACount & " row(s) affected)", vbOKOnly + vbInformation, "Tesseract")
    Catch ex As Exception
        MsgBox("Failed to update, please try again" & vbCrLf & vbCrLf & ex.Message, vbOKOnly + vbCritical, "SQL Error")
    End Try
    cnt.Close()
    cnt.Dispose()
普萨·庞杰伦德拉普

SQL Server现在可能支持传递参数数组。许多数据库不这样做,并且Microsoft Connect上仍对此有一个开放的请求这将是值得发现的。

您还应该打开Option StrictSQL_Arr被声明为字符串,但是您为其分配了XML文字,然后将该文字作为命令文本传递。

这将创建一个SQL语句,在该语句中,为ID列表中的每个项目指定了自己的参数,然后为其设置了值。它使用Id的一些随机数据来模拟一个变化的列表,并使用MySQL ...概念是相同的。

' test data: random set of IDs to update
Dim idList = Enumerable.Range(1, 2500).OrderBy(Function(r) RNG.Next()).Take(8).ToList()

Dim sql As String = <sql>
            UPDATE SampleX SET `Value`= @v WHERE Id IN (@theList)
          </sql>.Value

' create the parameter placeholders
' results in a list of "@pX" items where X is a number
Dim params = Enumerable.Range(1, idList.Count).
            Select(Function(q) String.Format("@q{0}", q)).
            ToList()

' join the list of parms to make '@q1, @q2...'
' then replace @thelist with that string
sql = sql.Replace("@theList", String.Join(",", params))

' run the query
Using dbcon As New MySqlConnection(MySQLConnStr)
    Using cmd As New MySqlCommand(sql, dbcon)

        ' specify the value
        cmd.Parameters.Add("@v", MySqlDbType.Int32).Value = -6

        ' loop to supply an Id value for each IN parameter
        ' placeholder created
        For n As Int32 = 0 To params.Count - 1
            cmd.Parameters.Add(params(n), MySqlDbType.Int32).Value = idList(n)
        Next

        dbcon.Open()
        Dim rows = cmd.ExecuteNonQuery()
    End Using

    ' debug/demo: show the results
    sql = "SELECT Name, Descr, Value, Country FROM SampleX WHERE Value=-6"
    Using cmd As New MySqlCommand(sql, dbcon)
        dtSample = New DataTable
        dtSample.Load(cmd.ExecuteReader())
        dgv1.DataSource = dtSample
    End Using
End Using

我们希望查询保持参数化,因此第一部分将创建一个@q1占位符列表-与要更新的ID一样多。要在循环中创建占位符,请执行以下操作:

Dim params As New List(Of String)
For n As Int32 = 0 To idList.Count - 1
    params.Add(String.Format("@q{0}", (n + 1).ToString()))
Next

接下来,代码将@theListSQL替换为列表的联接版本。结果:

UPDATE SampleX SET `Value`= @v WHERE Id IN (@q1,@q2,@q3,@q4,@q5,@q6,@q7,@q8)

如果IN子句处理的是字符串而不是整数,请在参数创建中添加勾号:String.Format("'@q{0}'",...

其余的很简单:为每个参数指定ID:

' params(n) e.g. "q1"  and idList(n) is the value e.g. 11111
cmd.Parameters.Add(params(n), MySqlDbType.Int32).Value = idList(n)

我的样本只是将a值设置为-6,以使其易于查找。有用:

在此处输入图片说明

最后,请注意,生成的SQL允许最大长度。该最大值取决于DB Provider,并且很大,但是如果您的IN子句有很多Id ,则可能需要将其分成几批。

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章