3

我最近继承了一个ASP的网站,我不熟悉。昨天,其中一个页面开始报错:

Microsoft VBScript runtime error '800a0009'

Subscript out of range: 'i'

default.asp, line 19

这是第 13-27 行的代码:

<%
set rs = Server.CreateObject("ADODB.Recordset")
rs.open "SELECT * FROM VENDORS_LIST_TBL WHERE inStr('"& dVendorStr &"','|'&ID&'|')", Cn

DIM dTitle(100), dDescription(100), dLink(100)
i = 0 : Do while NOT rs.EOF : i = i + 1
dTitle(i) = rs.fields.item("dTitle").value
dDescription(i) = rs.fields.item("dDescription").value
dLink(i) = rs.fields.item("dLink").value : if dLink(i) <> "" then dTitle(i) = "<a href=""" & dLink(i) & """>" & dTitle(i) & "</a>"
if NOT rs.EOF then rs.movenext
Loop
x = i

rs.Close : Set rs = Nothing
%>

关于这里发生了什么以及如何解决它的任何想法?

谢谢!

4

3 回答 3

2

The "solution" you chose is not very good. What if within 2 years there will be more than 500? You will forget all about this and waste hours yet again.

Instead of fixed size arrays you can just use dynamic arrays:

DIM dTitle(), dDescription(), dLink()
ReDim dTitle(0)
ReDim dDescription(0)
ReDim dLink(0)
i = 0
Do while NOT rs.EOF
    i = i + 1
    ReDim Preserve dTitle(i)
    ReDim Preserve dDescription(i)
    ReDim Preserve dLink(i)    
    dTitle(i) = rs.fields.item("dTitle").value
    dDescription(i) = rs.fields.item("dDescription").value
    dLink(i) = rs.fields.item("dLink").value
    If (Not(IsNull(dLink(i)))) And (dLink(i) <> "") Then
        dTitle(i) = "<a href=""" & dLink(i) & """>" & dTitle(i) & "</a>"
    End If
    rs.movenext
Loop

This will start with one (empty) item in each array - for some reason the code seems to need this - then on each iteration one more item will be added, preserving the others.

Note that I've also fixed small issue that might have caused trouble - in case of NULL value in "dLink" field, you would get blank anchors in your HTML because NULL is not empty string in VBScript.

于 2012-06-17T14:25:09.560 回答
2

您已将 dTitle、dDescription 和 dLink 声明为大小为 100 的数组。当您遍历记录集时,您正在为这些数组分配元素。您的记录集中似乎有 100 多条记录,因此逻辑尝试执行以下操作:

dTitle(101) = rs.fields.item("dTitle").value

这将引发错误,因为您的数组不足以容纳所有数据。

于 2012-06-16T15:31:27.940 回答
1

这如何GetRows可以用来实现相同的目标。

<% 

Function VendorSearch(sVendor)

    Dim cn:  Set cn = SomeLibraryFunctionThatOpensAConnection()
    Dim cmd: Set cmd = Server.CreateObject("ADODB.Command")
    cmd.CommandType = adCmdText
    cmd.CommandText = "SELECT dTitle, dDescription, dLink FROM VENDORS_LIST_TBL WHERE inStr(?,'|'&ID&'|')"
    cmd.Parameters.Append cmd.CreateParameter("Vendor", adVarChar, adParamInput, Len(sVendor), sVendor)
    Set cmd.ActiveConnection = cn
    Dim rs : Set rs = cmd.Execute()

    VendorSearch = rs.GetRows()

    rs.Close()
    cn.Close()
End Function

Dim arrVendor : arrVendor =  VendorSearch(dVendorStr)

Const cTitle = 0, cDesc = 1, cLink = 2

Dim i
For i = 0 To UBound(arrVendor, 2)
    If IsNull(arrVendor(cLink, i) Or arrVendor(cLink, i) = "" Then
        arrVendor(cTitle, i) = "<a href=""" & arrVendor(cLink, i) & """>" & arr(cTitle, i) & "</a>"
    End If 
Next

%> 

笔记:

  • Select 语句仅包含结果中需要的那些字段,应避免使用 *
  • 参数化命令用于避免来自 SQL 联系的 SQL 注入威胁。
  • 用于生成二维数组的字段索引的常量。
  • 虽然此代码复制了标题值的原始修改,但这仅作为示例。实际上,HTML 的构建应该尽可能晚,并且所有诸如标题和描述的字符串的输出都应该Server.HTMLEncode在发送到响应之前传递。
于 2012-06-18T12:49:22.063 回答