简体   繁体   English

在SQL查询中使用VBA组合框值返回类型不匹配

[英]Using VBA Combobox value in SQL Query returning type mismatch

I have a user form that contains a list of agents. 我有一个包含代理列表的用户表单。 When you click on an agent and click a button to mark them as not here, a popup comes up that requires you to pick a reason they aren't here. 当您单击代理并单击将其标记为不在此处的按钮时,会弹出一个对话框,要求您选择不在此处的原因。

This popup also contains a box that should display the current amount of attendance points the agent has. 该弹出窗口还包含一个框,该框应显示座席当前的出勤点数。 The code to pull that info from the SQL table where it's stored is below. 下面的代码从存储该信息的SQL表中提取该信息。

When it runs I get a type mismatch error on the .additem rs![Five9 Extension] line. 当它运行时,我在.additem rs![Five9 Extension]行上收到类型不匹配错误。 The column on the SQL table is a varchar and I just need it to display a number so I'm not really sure what the issue is. 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

Bang operator implicit default member calls aside ( rs![Field Name] is shorthand for rs.Fields("Field Name").Value ), it seems the query isn't returning what you think it does: 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) returns a Boolean , so the query you're sending is something like ListBox.Selected(index)返回一个Boolean ,因此您要发送的查询类似于

select [Five9 Extension] from dbo.[Master Staffing List] Where [Agent Name] ='True'

....Which I would expect to yield a grand total of 0 rows. ....我希望产生总计0行。

Question: what would happen if [Agent Name] were to be Jake O'Neil ? 问题:如果[Agent Name]Jake O'Neil ,会发生什么? That's right, a syntax error with the query. 没错,查询语法错误。 Now what if [Agent Name] were to be Robert'; DROP TABLE [Master Staffing List];-- 现在,如果[Agent Name]Robert'; DROP TABLE [Master Staffing List];-- Robert'; DROP TABLE [Master Staffing List];-- ? Robert'; DROP TABLE [Master Staffing List];-- That's right, very bad things . 是的, 非常糟糕的事情 This is called a SQL injection vulnerability , and it plagues database-queryuing code all over the world, whenever people concatenate WHERE clauses with user inputs. 这被称为SQL注入漏洞 ,每当人们将WHERE子句与用户输入连接在一起时,它就会困扰全世界的数据库查询代码。 It's not only a matter of database security, it's also a cause of easily avoidable bugs. 这不仅是数据库安全性的问题,也是容易避免的错误的原因。

Let's fix this. 让我们解决这个问题。 Use an ADODB.Command , and in your SQL string remove the single quotes and replace the parameter concatenation with a question mark: 使用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

Now for consuming the recordset, you can't assume that there will be rows - so you make a Do While loop that doesn't enter if rs.EOF is True : 现在要使用记录集,您不能假定将存在行-因此,如果rs.EOFTrue ,则创建一个Do While循环,该循环不会输入:

Do While Not rs.EOF
    '...consume recordset...
    rs.MoveNext
Loop

Now, only selectedName needs to be figured out. 现在,只需要找出selectedName即可。 Use the listbox' ListIndex property to do that: 使用列表框的ListIndex属性来执行此操作:

Dim selectedName As String
With MainPage.AgentName
    Debug.Assert .MultiSelect = fmMultiSelectSingle 'wheels come off otherwise
    selectedName = .List(.ListIndex)
End With

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM