【问题标题】:No Value given for 1 or more required parameters. Update SQL没有为 1 个或多个必需参数提供值。更新 SQL
【发布时间】:2023-03-31 06:22:01
【问题描述】:

我正在编写一个程序,当用户在列表视图中选择一条记录时,它会更新密码或积分。我收到一个错误“没有为 1 个或多个必需参数提供值”,我不知道如何纠正,我是否遗漏了一些明显的东西?

Dim sql As String = "UPDATE Users SET [Password] = @2,[LoyaltyPoints] = @3 WHERE [Username] = '" & mListView.SelectedItems(0).Text & "'"
cmd = New OleDbCommand(sql, con)

'ADD PARAMETER
cmd.Parameters.AddWithValue("@1", UpdatedUser)
cmd.Parameters.AddWithValue("@2", UpdatedPass)
cmd.Parameters.AddWithValue("@3", UpdatedPoints)


'OPEN CONNECTION,EXECUTE UPDATE,CLOSE CONNECTION'
Try
    con.Open()
    adapter = New OleDbDataAdapter(cmd)
    adapter.UpdateCommand = con.CreateCommand()
    adapter.UpdateCommand.CommandText = sql

    If (adapter.UpdateCommand.ExecuteNonQuery() = 0) Then 'Error Appears Here
        MsgBox("Successfully Updated")
        ClearAll()
    Else
        MsgBox("Unsuccessful")
     End If
     con.Close()
     Retrieve()

     Catch ex As Exception
         MsgBox(ex.Message)
         con.Close()
     End Try
End Sub

【问题讨论】:

  • 你能说明你在哪里获得更新用户/通行证/积分的值吗?
  • 您的代码仍然容易被 sql 注入攻击。您还应该参数化您的用户名。
  • ``` UpdatePass = edtUpdatePass.Text If UpdatePass = Nothing Then MsgBox("请确保整个表单已完成", MsgBoxStyle.Critical) ElseIf Val(edtUpdatePoints.Text) = 0 Then MsgBox(" Base Loyalty Points must be a Number", MsgBoxStyle.Critical) End If UpdatePoints = edtUpdatePoints.Text UpdateLV(sSelectedUser, UpdatePass, UpdatePoints) End If ``` 我的变量在哪里
  • 我很确定参数名称不能以数字开头:@1 = 失败,@p1 = 成功。另外,虽然使用SQL参数是正确的,但请注意AddWithValue is EvilAddWithValue is evil!Can we stop using AddWithValue() already?
  • @AndrewMorton 如果我将参数名称替换为“@P1”、“@P2”和“@P3”,我会得到同样的错误,我应该使用什么来代替 AddWithValue()?

标签: sql vb.net


【解决方案1】:

其他人已经指出了问题(和解决方案),但我想补充一点……避免命名参数 1、2、3 或 A、B、C。我敢打赌,如果你以与正在发送的数据相对应的方式命名它们,诊断问题会更容易。您在查询中缺少@1...但不要将其命名为@1:

Dim sql As String = "UPDATE Users SET [Password] = @PASS,[LoyaltyPoints] = @POINTS WHERE [Username] = @USER"
cmd = New OleDbCommand(sql, con)

cmd.Parameters.AddWithValue("@USER", UpdatedUser)
cmd.Parameters.AddWithValue("@PASS", UpdatedPass)
cmd.Parameters.AddWithValue("@POINTS", UpdatedPoints)

不要在伤口上撒盐,但你的解决方案是倒退了一大步。各项参数都不错。它们更适合数据库、更简洁的代码、完全安全,并且它们可以处理异常数据,例如,如果您传递的任何值中有单引号字符(如果发生这种情况,您的解决方案将崩溃​​)。

【讨论】:

  • 即使复制提供的代码,我仍然收到相同的错误“没有为一个或多个必需参数提供值”
  • 您的三个变量(UpdatedUser、UpdatedPass、UpdatedPoints)是否为空?
  • 它会在adapter.UpdateCommand.ExecuteNonQuery 抛出一个错误,此时所有 3 个变量都已赋值
  • 您需要按照它们在SQL中出现的顺序将参数添加到命令中。
  • so like cmd.Parameters.AddWithValue("@PASS", UpdatedPass) cmd.Parameters.AddWithValue("@POINTS", UpdatedPoints) cmd.Parameters.AddWithValue("@USER", UpdatedUser) 如果是这样,它会抛出同样的错误
【解决方案2】:

代码应该是这样的:

Dim updatedUser = mListView.SelectedItems(0).Text

Dim sql As String = "UPDATE Users SET [Password] = @pass, [LoyaltyPoints] = @points WHERE [Username] = @username"

Using conn As New OleDbConnection("your connection string"),
        cmd As New OleDbCommand(sql, conn)

    'TODO: Use the correct values for each .OleDbType and .Size parameter.
    cmd.Parameters.Add(New OleDbParameter With {.ParameterName = "@pass", .OleDbType = OleDbType.VarWChar, .Size = 99, .Value = updatedPass})
    cmd.Parameters.Add(New OleDbParameter With {.ParameterName = "@points", .OleDbType = OleDbType.Integer, .Value = updatedPoints})
    cmd.Parameters.Add(New OleDbParameter With {.ParameterName = "@username", .OleDbType = OleDbType.VarWChar, .Size = 99, .Value = updatedUser})

    Try
        conn.Open()

        If cmd.ExecuteNonQuery() = 0 Then
            MsgBox("Unsuccessful")
            ClearAll()
        Else
            MsgBox("Successfully Updated")
        End If

        Retrieve()

    Catch ex As Exception
        MsgBox(ex.Message)
    End Try

End Using

【讨论】:

【解决方案3】:

我明白了,我必须对 SQL 文本进行调整

        Dim sql As String = "UPDATE Users SET [Password] = '" + UpdatedPass + "',[LoyaltyPoints] = '" + UpdatedPoints + "' WHERE [Username] = '" & mListView.SelectedItems(0).Text & "'"
        cmd = New OleDbCommand(sql, con)

        'OPEN CONNECTION,EXECUTE UPDATE,CLOSE CONNECTION'
        Try
            con.Open()
            adapter = New OleDbDataAdapter(cmd)
            adapter.UpdateCommand = con.CreateCommand()
            adapter.UpdateCommand.CommandText = sql

            If (adapter.UpdateCommand.ExecuteNonQuery() > 0) Then
                MsgBox("Successfully Updated")
            Else
                MsgBox("Unsuccessful")
            End If
            con.Close()
            Retrieve()

        Catch ex As Exception
            MsgBox(ex.Message)
            con.Close()
        End Try

【讨论】:

  • 看起来您已经通过删除参数“修复”了这个特定问题。这是一个可能导致 sql 注入攻击的错误。我强烈建议您使用参数而不是通过连接字符串来构建 sql 语句。
  • 你建议我如何使它最安全?我必须对原始代码进行哪些更改才能使用参数?
  • 您的原始代码使用了参数。我不确定您遇到的错误。我注意到您创建了一个 @1 参数,但从未在您的 sql update 语句中使用它。也许这就是问题所在。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多