soword科技言
永久公益免费API接口
提供永久免费的API接口,查看更多API接口,如果您有其他免费API资源,请联系我们,造福人类。
提供商务开发:小程序,系统,APP
定制开发,免费评估,免费咨询,价格便宜,售后保障,前往开发服务中心联系开发客服中心
将vbscript字符串列表传递给SQL“ in”运算符

在vb脚本中,我有一条select语句,我试图将长度不确定的字符串值传递给SQL in运算符,以下代码有效,但允许进行SQL注入。

我正在寻找一种使用ADO createParameter方法的方法。我认为我尝试过的不同方法都陷入了我的数据类型(adVarChar,adLongChar,adLongWChar)

Dim studentid 
studentid = GetRequestParam("studentid")Dim rsGetData, dbCommandSet dbCommand = Server.CreateObject("ADODB.Command")
Set rsGetData = Server.CreateObject("ADODB.Recordset")
dbCommand.CommandType = adCmdText
dbCommand.ActiveConnection = dbConn
dbCommand.CommandText = "SELECT * FROM students WHERE studentID in (" & studentid & ")"Set rsGetData = dbCommand.Execute()

我试过了

Call addParameter(dbCommand, "studentID", adVarChar, adParamInput, Nothing, studentid)

这给了我这个错误ADODB.Parameters错误'800a0e7c'添加参数(studentID)=('SID0001','SID0010')时出现问题:参数对象定义不正确。提供的信息不一致或不完整。

我也尝试过

Call addParameter(dbCommand, "studentID", adLongVarChar, adParamInput, Nothing, studentid)

Dim studentid 
studentid = GetRequestParam("studentid")Dim slength
slength = Len(studentid)response.write(slength)Dim rsGetData, dbCommandSet dbCommand = Server.CreateObject("ADODB.Command")
Set rsGetData = Server.CreateObject("ADODB.Recordset")
dbCommand.CommandType = adCmdText
dbCommand.ActiveConnection = dbConn
dbCommand.CommandText = "SELECT * FROM students WHERE studentID in (?)"
Call addParameter(dbCommand, "studentID", adVarChar, adParamInput, slength, studentid)Set rsGetData = dbCommand.Execute()

这两个选项均不执行任何操作...没有错误消息,并且未执行SQL。

附加信息:

通过HTML表单文本区域输入了studentid。该设计应能够让用户输入学生ID的列表(最多1000行)并在这些学生资料上执行操作。在上一个asp的javascript中,我有一个函数来接收列表并将其更改为逗号分隔的列表,并在列表中的每个元素周围加上''。

经典ASP对此没有很好的支持。您需要使用此处讨论的替代方法之一:

http://www.sommarskog.se/arrays-in-sql-2005.html

那篇文章有点长,但是用一种很好的方式:很多人认为这是该主题的标准著作。

碰巧的是,我的首选选项未包含在该文章中。我想做的是为列表中的每个项目使用一个保留表,以便每个项目都使用ajax请求在用户选择或取消选择时将其从保留表中插入或删除。然后,我加入该表作为我的列表,这样您就可以得到如下内容:

SELECT s.* FROM students s
INNER JOIN studentSelections ss on s.StudentID = ss.StudentIDWHERE ss.SessionKey = ?

您的addParameter()职能是什么?我在您的代码的任何地方都看不到。

您应该能够像这样创建和添加字符串参数:

With dbCommand.Parameters.Append .CreateParameter(, vbString, , Len(studentid), studentid)End With

(这里的小技巧。vbString与的价值相同adBSTR。您会发现,VarType所有VB“类型”的都有匹配的ADO对应项。)

Type VarType (VBScript)DataTypeEnum (ADO)Value--------------------------------------------------IntegervbInteger adSmallInt, 2-byte2Long vbLongadInteger, 4-byte 3Single vbSingleadSingle4Double vbDoubleadDouble5Currency vbCurrencyadCurrency6Date vbDateadDate7String vbStringadBSTR8Object vbObjectadIDispatch 9ErrorvbError adError10BooleanvbBoolean adBoolean11VariantvbVariant adVariant12Byte vbByteadUnsignedTinyInt17

编辑:看起来乔尔为您提供了一个很好的解决方案。我没有意识到IN与ADO参数化查询不兼容。我认为类似以下内容的方法可能会起作用,但您可能不想(可能)使用1000个ID。

' Create array from student IDs entered...
a = Split(studentid, ",")

' Construct string containing proper number of param placeholders. Remove final comma.strParams = Replace(String(UBound(a) - 1, "?"), "?", "?,")strParams = Left(strParams, Len(strParams) - 1)With dbCommand.CommandText = "select * from students where studentID in (" & strParams & ")"
Set rsGetData = .Execute(, a)End With

阅读了乔尔(Joel)提供的文章以及All Blond提供的答案之后,这就是最终为我工作的解决方案。

Dim studentid
studentid = GetRequestParam("studentid")Dim splitStudentid, x
splitStudentid = Split(studentid,",")for x=0 to Ubound(splitStudentid)Dim rsGetData, dbCommand, originSIDSet dbCommand = Server.CreateObject("ADODB.Command")Set rsGetData = Server.CreateObject("ADODB.Recordset")dbCommand.CommandType = adCmdText
dbCommand.ActiveConnection = dbConn
dbCommand.CommandText = "SELECT * FROM students WHERE studentID=?"Call addParameter(dbCommand, "studentID", adVarChar, adParamInput, 35, splitStudentid(x))Set rsGetData = dbCommand.Execute()If (NOT rsGetData.EOF) Then 
originSID = rsGetData.Fields(0)
//additional codeEnd Ifnext

我发现在我的代码中没有优雅的方式使用“ in”运算符。我也决定反对存储过程,因为这是一个简单的查询,尽管我同意

我还意识到addParameter是我公司内部使用的功能,因此下面是一个可行的附加解决方案,但不是我公司的偏好。

Dim studentid
studentid = GetRequestParam("studentid")Dim splitStudentid, x
splitStudentid = Split(studentid,",")for x=0 to Ubound(splitStudentid)Dim rsGetData, dbCommand, originSIDSet dbCommand = Server.CreateObject("ADODB.Command")Set rsGetData = Server.CreateObject("ADODB.Recordset")dbCommand.CommandType = adCmdText
dbCommand.ActiveConnection = dbConn
dbCommand.CommandText = "SELECT * FROM students WHERE studentID=?"Set rsGetData = dbCommand.Execute(, Array(splitStudentid(x)))If (NOT rsGetData.EOF) Then 
originSID = rsGetData.Fields(0)
//additional codeEnd Ifnext

IN与参数化查询一起使用并不困难

将此问题另一个该问题重复的问题发布在此处

这并不像您想的那样困难,adCmdText查询只需要查询中的占位符以匹配参数数量及其顺序位置即可,并且可以与您传递到IN语句中的任意数量的参数一起使用

这是在SQL Server中使用AdventureWorks示例数据库的快速示例。我们使用Array来存储Person.Contact要过滤的每条记录的ID,IN然后在执行之前根据该数组动态构建参数ADODB.Command

注意:数组的来源并不重要,它可以是一个字符串列表,该字符串列表可以Split()进入Array或只是一个Array()调用(如本示例中使用的那样)

<%Option explicit%><!-- #include virtual = "/config/data.asp" --><%Dim cmd, rs, sql, data, rows, row'Our example parameters as an Array for the IN statement.Dim ids: ids = Array(2, 5, 10)Dim id

sql = ""sql = sql & "SELECT [FirstName], [LastName] " & vbCrLf
sql = sql & "FROM Person.Contact " & vbCrLf
sql = sql & "WHERE [ContactId] IN (?, ?, ?) " & vbCrLf
sql = sql & "ORDER BY [LastName], [FirstName]" & vbCrLfSet cmd = Server.CreateObject("ADODB.Command")With cmd.ActiveConnection = conn_string.CommandType = adCmdText.CommandText = SQL'Loop through the Array and append the required parameters.
For Each id in idsCall .Parameters.Append(.CreateParameter("@id" & id, adInteger, adParamInput, 4))
.Parameters("@id" & id).Value = idNext
Set rs = .Execute()
'Output the Recordset to a 2-Dimensional Array
If Not rs.EOF Then data = rs.GetRows()
Call rs.Close()End WithSet cmd = NothingIf IsArray(data) Then
rows = UBound(data, 2)
For row = 0 To rowsCall Response.Write("<p>" & data(0, row) & " " & data(1, row) & "</p>" & vbCrLf)
NextEnd If%>

输出:

<p>Catherine Abel</p><p>Pilar Ackerman</p><p>Ronald Adina</p>



2023-03-22 10:04:19

新人小程序+APP定制199元起


发放福利,助力中小企业发展,真正在互联网中受益

点击询问定制

广告服务展示