【问题标题】:How to filter data parsed from database using ASP如何使用 ASP 过滤从数据库中解析的数据
【发布时间】:2020-02-04 20:55:11
【问题描述】:

我最近接触了一个非常混乱的 ASP 项目。我不熟悉该语言,但在网上搜索了一段时间后,我设法学习了它,但我仍然不熟悉数据库查询等。

所以问题来了,我有这段代码可以从 MS Access 数据库文件中获取数据。我想要的是根据传递的 post/get 参数过滤这些数据。

这是我目前的代码:

sql = "SELECT * FROM tyres"

if len(brand1) > 2 then 
     sql = sql & " WHERE brand = '" & brand1 & "' AND application = '" & season1 & "'"

if len(brand2) > 2 then 
     sql = sql & " or brand = '" & brand2 & "' AND application = '" & season2 & "'"

if len(brand3) > 2 then 
    sql = sql & " or brand = '" & brand3 & "' AND application = '" & season3 & "'"

if len(brand4) > 2 then 
    sql = sql & " or brand = '" & brand4 & "' AND application = '" & season4 & "'"

if len(brand5) > 2 then 
    sql = sql & " or brand = '" & brand5 & "' AND application = '" & season5 & "'"

set Dataconn = Server.CreateObject("ADODB.Connection") 
Dataconn.Open "database-in"
set DataTable = Server.CreateObject("ADODB.recordset")
DataTable.Open sql, Dataconn

而且它似乎不起作用。请注意,用户最多可以插入 5 个(如您所见)不同的参数,以便在数据库中搜索产品。因此,如果您对如何使这项工作有任何进一步的信息,请随时提出建议。

【问题讨论】:

  • 恐怕你需要扔掉你的代码。 从不通过连接字符串来构建 SQL 语句。这样做最多会导致运行时错误和错误,最坏的情况是 SQL 注入攻击。
  • 另一个观察结果是您计算了变量名称(brand1 .. brandNseason1 .. seasonN)。这意味着您实际上需要一个名为 brandseason 的数组。显示当前如何创建这些变量。
  • @Tomalak 好吧,实际上有点复杂。我希望每个都是一个单独的结果数组。例如,我想获得基于品牌 1 和季 1 的结果,然后是品牌 2 和季 2 等,而不是相互混合
  • 这根本不是问题。但首先你真的需要摆脱计数变量和随之而来的代码重复。
  • @Tomalak 你是什么意思?我有 5 个不同的输入,它们将过滤数据

标签: sql database ms-access asp-classic adodb


【解决方案1】:

从字符串连接创建 SQL 是非常不明智的,如果这些字符串部分来自用户输入,甚至直接输出 dangerous

ADODB 等数据库库针对这种情况有commandsparameters。他们使用带有占位符的固定 SQL 字符串,并且库确保不会发生任何不良事件,无论用户提供的值是什么。

这也意味着我们可以预先准备一条 SQL 语句,并在页面的整个生命周期内多次重复使用它。

Dim Conn ' As ADODB.Connection
Dim Cmd  ' As ADODB.Command

Set Conn = Server.CreateObject("ADODB.Connection")
Set Cmd = Server.CreateObject("ADODB.Command")

Conn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\path\to\your\database.accdb;"

' prepare a reusable command with parameters (i.e. placeholders)
With Cmd
  Set .ActiveConnection = Conn
  .CommandType = adCmdText
  .CommandText = "SELECT Field1, Field2, Field3 WHERE brand = @brand AND application = @season"

  ' set up the parameters for each placeholder
  '  - use proper datatypes here, as per your DB
  '  - varchar types need a defined length
  .Parameters.Append .CreateParameter("@brand", adVarChar, , 50)
  .Parameters.Append .CreateParameter("@season", adVarChar, , 100)
End With

' helper function that operates the Command object and returns a RecordSet
Function SearchTyres(brand, season)
  Cmd.Parameters("@brand", brand)
  Cmd.Parameters("@season", season)
  Set SearchTyres = Cmd.Execute
End With

在您的代码中可以方便地使用特定于 ADODB 的常量,例如 adCmdTextadVarChar。为了让它们在任何地方都能轻松使用,您需要在 global.asa 文件中声明 ADODB 类型库(如果没有,请创建一个),并将其添加到文件顶部:

<!--metadata 
    type="TypeLib" 
    name="Microsoft ActiveX Data Objects 6.1 Library" 
    uuid="B691E011-1797-432E-907A-4D8C69339129"
    version="6.1"
-->

现在您可以在页面中使用它,例如:

If Len(brand1) > 2 Then
  With SearchTyres(brand1, season1)
    ' ...let's do something with the RecordSet
    While Not .EOF
      Response.Write Server.HTMLEncode(!Field1) & "<br>"
      .MoveNext
    Wend
  End With
End If

注意事项

  • 不要这样做SELECT * - 总是写出你想要的字段。
  • 声明类型库并不是绝对必要的,但如果不声明,则必须自己定义所有常量,如 adVarChar,这比它的价值要麻烦得多。
  • With SearchTyres(...)

    的方便简写
    Dim Rs
    Set Rs = SearchTyres(...)
    With Rs
      ' ...
    End With
    
  • Rs!Field1Rs.Fields("Field1") 的便捷简写。在With Rs 块内,Rs 本身是可选的,所以一个普通的!Field1 实际上是有意义的。

  • 最后,它有助于在 MS Office 产品(如 Word)的 VBA IDE 中创建代码。使用 Tools/References 来引用相同的 ADODB 类型库。 VBA 和 VBS 不是 100 代码兼容的,但 VBA IDE 具有 Intellisense,一个适当的调试器,使用相同的对象,代码只需很少的更改即可传输到 ASP。

【讨论】:

  • 谢谢!还有一件事,这里的问题是从复选框传递的值没有用单引号括起来(所以我可以使用 WHERE ... IN 语句)。我尝试使用 Split() 函数,但它创建了许多代码行.有什么想法吗?
  • 你还在想“SQL 是一个字符串,我需要单引号” 术语。您不需要单引号,WHERE ... IN 语句中不需要,其他任何地方都不需要。你需要参数。
  • 我明白了!谢谢,我试试看! :)
  • 在准备好的语句中使用IN 有点复杂,因为所需的参数数量不再是固定的,也不再是提前知道的。但这绝对是可行的。例如,如果有三个值,您在 Command 对象中准备好的 SQL 字符串需要看起来像这样:... WHERE field IN (?, ?, ?),并且您需要调用 .Parameters.Append 三次。
  • 是的,但在这种情况下,参数的数量从 1 到 15-16 不等,每个用户选择不同数量的参数。例如,有 13 个品牌,但一个用户可能选择 2 个品牌,另一个用户可能选择 4 个,等等......
【解决方案2】:

因为其他人都在忙着抨击你,而不是真正回答你如何构建你的 sql 字符串的问题:

<%

    SqlStr = "SELECT * FROM Tyres WHERE 1 = 1 " 
    If Len(brand1) > 2 OR  Len(brand2) > 2 OR  Len(brand3) > 2 OR  Len(brand4) > 2 OR  Len(brand5) > 2 Then
        BrandInStr = " AND brand IN("
            If Len(brand1) > 2 Then
                BrandInStr = BrandInStr & "'" & brand1 & "',"    
            End If          
            If Len(brand2) > 2 Then
                BrandInStr = BrandInStr & "'" & brand2 & "',"    
            End If              
            If Len(brand3) > 2 Then
                BrandInStr = BrandInStr & "'" & brand3 & "',"    
            End If              
            If Len(brand4) > 2 Then
                BrandInStr = BrandInStr & "'" & brand4 & "',"    
            End If                  
            If Len(brand5) > 2 Then
                BrandInStr = BrandInStr & "'" & brand5 & "',"    
            End If  
        BrandInStr = Left(BrandInStr,Len(BrandInStr)-1)             
        BrandInStr = BrandInStr & ") "
    End If
    If Len(season1) > 2 OR  Len(season2) > 2 OR  Len(season3) > 2 OR  Len(season4) > 2 OR  Len(season5) > 2 Then
        SeasonInStr = " AND Season IN("
            If Len(Season1) > 2 Then
                SeasonInStr = SeasonInStr & "'" & Season1 & "',"    
            End If          
            If Len(Season2) > 2 Then
                SeasonInStr = SeasonInStr & "'" & Season2 & "',"    
            End If              
            If Len(Season3) > 2 Then
                SeasonInStr = SeasonInStr & "'" & Season3 & "',"    
            End If              
            If Len(Season4) > 2 Then
                SeasonInStr = SeasonInStr & "'" & Season4 & "',"    
            End If      
            If Len(Season5) > 2 Then
                SeasonInStr = SeasonInStr & "'" & Season5 & "',"  
            End If  
        SeasonInStr = Left(SeasonInStr,Len(SeasonInStr)-1)              
        SeasonInStr = SeasonInStr & ") "
    End If

    SqlStr = SqlStr & BrandInStr & " " & SeasonInStr

%>

但是,如果您的变量作为单个逗号分隔的字符串(而不是编号)传递,那会容易得多

<%

    SqlStr = "SELECT * FROM Tyres WHERE 1 = 1 "

    If Len(Trim(Replace(Replace(Brand," ",""),",","") > 0 Then
       SqlStr = SqlStr & "AND Brand In('" & Replace(Brand,",","','") & "') "
    End If


    If Len(Trim(Replace(Replace(Season," ",""),",","") > 0 Then
       SqlStr = SqlStr & "AND Season In('" & Replace(Season,",","','") & "') "
    End If

%>

【讨论】:

  • 羞辱你给出的建议绝对是你不应该做的一件事。
  • 也许,当人们似乎过度抨击某件事时,那可能是个坏主意。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-10-03
  • 1970-01-01
  • 2020-01-08
相关资源
最近更新 更多