在SQL Query中使用VBA Combobox值返回类型不匹配

时间:2018-04-27 13:33:28

标签: sql excel vba

我有一个包含代理列表的用户表单。当您单击代理并单击按钮将其标记为不在此处时,会出现一个弹出窗口,要求您选择他们不在的原因。

此弹出窗口还包含一个框,该框应显示代理所具有的当前出勤点数量。从存储它的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

1 个答案:

答案 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 Whilers.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