参数化 SQL UPDATE 语句

Posted

技术标签:

【中文标题】参数化 SQL UPDATE 语句【英文标题】:Parameterized SQL UPDATE Statement 【发布时间】:2016-11-16 22:24:11 【问题描述】:

我见过很多参数化 SQL 查询的示例,但遇到了一些问题。

我知道我没有散列密码,所以请忽略它。

以下是我的代码:

cmd.CommandText = "UPDATE users SET username=@uName, pwd=@pWord, role=@uRole, actuser=@uActive WHERE ID=" & recordID
cmd.Parameters.AddWithValue("@uName", tbUsername.Text)
cmd.Parameters.AddWithValue("@pWord", tbPassword1.Text)
cmd.Parameters.AddWithValue("@uRole", cbRole.SelectedItem)
cmd.Parameters.AddWithValue("@uActive", isActive)

我得到的错误是:

“条件表达式中的数据类型不匹配”

我不明白为什么,因为数据库中的所有内容都是“短字符串”,但当代码尝试运行时,“actuser”设置为“是/否”并且“isActive”设置为“是”。我已经验证表格列标题是准确的,但我不知道为什么这不起作用。

这种格式似乎适用于 INSERT 语句,但不适用于 UPDATE 语句......但我目前无法确认。

任何帮助将不胜感激。

编辑:

更新了同样错误的代码。

 Dim isActive As Boolean = False
    If cbxActive.CheckState = CheckState.Checked Then
        isActive = "True"
    End If

    cmd.CommandText = "UPDATE users SET username=@uName, pwd=@pWord, role=@uRole, actuser=@uActive WHERE ID=@ID"
    cmd.Parameters.AddWithValue("@uName", tbUsername.Text)
    cmd.Parameters.AddWithValue("@pWord", tbPassword1.Text)
    cmd.Parameters.AddWithValue("@uRole", cbRole.SelectedItem.ToString())
    cmd.Parameters.AddWithValue("@uActive", If(isActive, "Yes", "No"))
    cmd.Parameters.AddWithValue("@ID", recordID)

    myConnection.Open()
    Try
        cmd.ExecuteNonQuery()
    Catch ex As OleDb.OleDbException
        MsgBox(ex.Message)
        Exit Sub
    End Try`

SelectedItem 正在从组合框中的集合中返回一个字符串。

这是我的数据库结构。Link to Picture of Access DB structure

这是另一个结构图。 enter image description here

【问题讨论】:

不要使用AddWithValue - 它使提供者猜测数据类型。 cbRole.SelectedItem 例如是对象。通常有更多的异常表明哪种类型会给你一个线索。当然我们不知道isActive 是什么类型——听起来应该是布尔值,但我们看不到它的声明。 recordID 可以/应该也是一个参数。 except for "actuser" which is set to Yes/No and "isActive" is set to "Yes" 有问题(如果描述准确)。首先,mysql 没有是/否列类型,通常你会使用 tinyint。但是是/否是一种访问主义,但它只是布尔值的另一个名称。如果你传递"Yes",那是一个不匹配的字符串 只是猜测,因为您的代码没有显示变量或数据库表的声明:recordId 是正确的数据类型吗? 几页文档,link 对不起,我应该注意到“isActive”被声明为字符串。 'Dim isActive As String If cbxActive.CheckState = CheckState.Checked Then isActive = "Yes" Else isActive = "No" End If' 这是一个访问数据库,而不是 mySQL。标签不正确。 【参考方案1】:

当然,我们只能猜测 isActivecbRole.SelectedItem 中的内容,但我们可以肯定的是,如果不是两者都有,其中之一会导致您的问题。

具体来说,只有在使用直接匹配类型时才能使用AddWithValue。否则你需要像这样精确设置参数数据类型

Dim p As New OleDbParameter(@pName, OleDbType.SomeType)
p.Value = [your value]
cmd.Parameters.Add(p)

在您的情况下,这两行可能是 [scratch that]!有问题的

cmd.Parameters.AddWithValue("@uRole", cbRole.SelectedItem)
cmd.Parameters.AddWithValue("@uActive", isActive)

第一行返回可以是任何东西的对象(只有你知道)。如何处理它

' If selected item is string
cmd.Parameters.AddWithValue("@uRole", cbRole.SelectedItem.ToString())
' If selected item is integer
cmd.Parameters.AddWithValue("@uRole", CInt(cbRole.SelectedItem))
' If selected item is complex object in which you use property
Dim val As Integer = DirectCast(cbRole.SelectedItem, MyObjectType).SomeIntProperty
cmd.Parameters.AddWithValue("@uRole", val)

' If your value 'isActive' is boolean and you keep Yes/No in DB, you need this
cmd.Parameters.AddWithValue("@uActive", if(isActive, "Yes", "No"))
' and opposite
cmd.Parameters.AddWithValue("@uActive", if(isActive = "Yes", 1, 0))
' you have to be careful here. In .NET false=0, all else <> 0. so, if your business logic needs True=1, all else <> 1, you need to convert correspondingly 

最后一件事 - 为什么不参数化...WHERE ID=" &amp; recordID...?做同样的事情

cmd.CommandText = ". . . . . WHERE ID= @id"
cmd.Parameters.AddWithValue("@id", recordID)

【讨论】:

@MattBrown 所以,你需要使用if(isActive = "Yes", 1, 0)。另外,当我说“结构”时,我的意思是:用户 varchar; id 整数....等 非常感谢,这是正确的并解决了问题!很抱歉没有发布准确的第一篇文章,我会在未来这样做。我是参数化的新手,你的建议和技巧真的帮助了我学习!再次感谢您! @MattBrown 享受!不要忘记投票。谢谢

以上是关于参数化 SQL UPDATE 语句的主要内容,如果未能解决你的问题,请参考以下文章

使用参数化SQL语句进行模糊查找(转载)

为什么要参数化执行SQL语句呢?

sql参数化查询

SQL Server中语句的自动参数化

ADO.NET复习总结--参数化SQL语句

执行sql语句时参数化,有啥好处