参数化 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】:
当然,我们只能猜测 isActive
和 cbRole.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=" & recordID...
?做同样的事情
cmd.CommandText = ". . . . . WHERE ID= @id"
cmd.Parameters.AddWithValue("@id", recordID)
【讨论】:
@MattBrown 所以,你需要使用if(isActive = "Yes", 1, 0)
。另外,当我说“结构”时,我的意思是:用户 varchar; id 整数....等
非常感谢,这是正确的并解决了问题!很抱歉没有发布准确的第一篇文章,我会在未来这样做。我是参数化的新手,你的建议和技巧真的帮助了我学习!再次感谢您!
@MattBrown 享受!不要忘记投票。谢谢以上是关于参数化 SQL UPDATE 语句的主要内容,如果未能解决你的问题,请参考以下文章