我有一个包含代理列表的用户表单。当您单击代理并单击按钮将其标记为不在此处时,会出现一个弹出窗口,要求您选择他们不在的原因。
此弹出窗口还包含一个框,该框应显示代理所具有的当前出勤点数量。从存储它的SQL表中提取该信息的代码如下。
运行时,.additem rs![Five9 Extension]
行出现类型不匹配错误。 SQL表上的列是varchar
,我只需要它来显示一个数字,所以我不确定问题是什么。
Dim Cn As ADODB.Connection
Dim Server_Name As String
Dim Database_Name As String
Dim SQLStr As String
Dim rs As ADODB.Recordset
Set rs = New ADODB.Recordset
Server_Name = "SDL02-VM25"
Database_Name = "PIA"
SQLStr = "select [Five9 Extension] from dbo.[Master Staffing List] Where [Agent Name] ='" & MainPage.AgentName.Selected(itemIndex) & "'"
Set Cn = New ADODB.Connection
Cn.Open "Driver={SQL Server};Server=" & Server_Name & ";Database=" & Database_Name & ""
rs.Open SQLStr, Cn, adOpenStatic
With ReasonPopup.CurPoints
.Clear
Do
.AddItem rs![Five9 Extension]
rst.MoveNext
Loop Until rst.EOF
End With
rs.Close
Cn.Close
Set rs = Nothing
Set Cn = Nothing
Exit Sub
答案 0 :(得分:0)
Bang操作符隐式默认成员调用(rs![Field Name]
是rs.Fields("Field Name").Value
的简写),似乎查询没有返回您认为的操作:
SQLStr = "select [Five9 Extension] from dbo.[Master Staffing List] Where [Agent Name] ='" & MainPage.AgentName.Selected(itemIndex) & "'"
ListBox.Selected(index)
会返回Boolean
,因此您发送的查询类似于
select [Five9 Extension] from dbo.[Master Staffing List] Where [Agent Name] ='True'
....我期望总共产生0行。
问题:如果[Agent Name]
为Jake O'Neil
会怎样?没错,查询语法错误。现在如果[Agent Name]
是Robert'; DROP TABLE [Master Staffing List];--
怎么办?没错,非常糟糕的事情。这称为 SQL注入漏洞,每当人们将WHERE子句与用户输入连接时,它就会在全世界困扰数据库查询代码。这不仅是数据库安全性的问题,也是容易避免的错误的原因。
我们解决这个问题。使用ADODB.Command
,并在SQL字符串中删除单引号,并将参数连接替换为问号:
Dim cmd As ADODB.Command
Set cmd = New ADODB.Command
Set cmd.ActiveConnection = Cn
cmd.CommandText = "SELECT [Five9 Extension] FROM dbo.[Master StaffingList] WHERE [Agent Name] = ?"
cmd.CommandType = adCmdText
cmd.Parameters.Append cmd.CreateParameter(Type:=adVarChar, Value:=selectedName)
Set rs = cmd.Execute
现在,为了使用记录集,您不能假设存在行 - 因此如果Do While
为rs.EOF
,则会导致True
循环无法进入:
Do While Not rs.EOF
'...consume recordset...
rs.MoveNext
Loop
现在,只需要计算selectedName
。使用列表框“ListIndex
属性执行此操作:
Dim selectedName As String
With MainPage.AgentName
Debug.Assert .MultiSelect = fmMultiSelectSingle 'wheels come off otherwise
selectedName = .List(.ListIndex)
End With