【问题标题】:Using Stored Procedure in Classical ASP .. execute and get results在经典 ASP 中使用存储过程 .. 执行并获取结果
【发布时间】:2014-02-20 17:59:02
【问题描述】:

我整天都在尝试解决这个问题,但它似乎对我不起作用。我想执行一个命令并将结果返回到记录集。

问题是两件事之一:要么我得到一个空响应,要么我的代码有问题。我确信这个命令应该从数据库中获取几行。我在循环中添加了response.write,但它们从未被打印出来。

代码如下:

Set conn = Server.CreateObject("ADODB.Connection")
conn.open "PROVIDER=SQLOLEDB;DATA SOURCE=X;DATABASE=Y;UID=Z;PWD=W;"
Set objCommandSec = CreateObject("ADODB.Command")
With objCommandSec
    Set .ActiveConnection = Conn
    .CommandType = 4
    .CommandText = "usp_Targets_DataEntry_Display"
    .Parameters.Append .CreateParameter("@userinumber ", 200, 1, 10, inumber)
    .Parameters.Append .CreateParameter("@group ", 200, 1, 50, "ISM")
    .Parameters.Append .CreateParameter("@groupvalue", 200, 1, 50, ismID)
    .Parameters.Append .CreateParameter("@targettypeparam ", 200, 1, 50, targetType)
End With 
    
set rs = Server.CreateObject("ADODB.RecordSet") 
rs = objCommandSec.Execute

while not rs.eof
    response.write (1)
    response.write (rs("1_Q1"))
    rs.MoveNext
wend
response.write (2)

已编辑 修改代码后,按照@Joel Coehoorn 的回答,解决方案是:

set rs = Server.CreateObject("ADODB.RecordSet") 
rs.oppen objCommandSec

而不是...

set rs = Server.CreateObject("ADODB.RecordSet") 
rs = objCommandSec.Execute

【问题讨论】:

  • +1 仅用于在旧 asp 中使用参数化查询。
  • @JoelCoehoorn 谢谢,我尝试了最好的方法。那么你有什么建议吗?

标签: sql asp-classic ado


【解决方案1】:

合作多年后的一些提示

  1. 无需创建ADODB.Connection,您可以将连接字符串直接传递给ADODB.Command 对象的.ActiveConnection 属性。这有两个好处,您不必实例化和打开另一个对象,并且由于上下文与ADODB.Command 绑定,它将与Set objCommandSec = Nothing 一起释放。

  2. .Execute 返回关闭记录集的一个常见原因是由于SET NOCOUNT ON 未在 SQL 存储过程中设置,因为INSERTUPDATE 将生成受影响的记录计数和关闭记录集。设置 SET NOCOUNT ON 将停止这些输出,并且只会返回您预期的记录集。

  3. 使用ADODB.Recordset 循环浏览您的数据是多余的,除非您需要前后移动并支持标准功能(例如在屏幕上显示记录集)不需要的一些较少使用的方法。请尝试使用Array

    Const adParamInput = 1
    Const adVarChar = 200
    Dim conn_string, row, rows, ary_data
    
    conn_string = "PROVIDER=SQLOLEDB;DATA SOURCE=X;DATABASE=Y;UID=Z;PWD=W;"
    
    Set objCommandSec = CreateObject("ADODB.Command")
    With objCommandSec
      .ActiveConnection = conn_string
      .CommandType = 4
      .CommandText = "usp_Targets_DataEntry_Display"
      .Parameters.Append .CreateParameter("@userinumber", adVarChar, adParamInput, 10, inumber)
      .Parameters.Append .CreateParameter("@group", adVarChar, adParamInput, 50, "ISM")
      .Parameters.Append .CreateParameter("@groupvalue", adVarChar, adParamInput, 50, ismID)
      .Parameters.Append .CreateParameter("@targettypeparam", adVarChar, adParamInput, 50, targetType)
    
      Set rs = .Execute()
      If Not rs.EOF Then ary_data = rs.GetRows()
      Call rs.Close()
      Set rs = Nothing
    End With
    Set objCommandSec = Nothing
    
    'Command and Recordset no longer needed as ary_data contains our data.
    If IsArray(ary_data) Then
      ' Iterate through array
      rows = UBound(ary_data, 2)
      For row = 0 to rows
        ' Return our row data
        ' Row N column 2 (index starts from 0)
        Call Response.Write(ary_data(1, row) & "")
      Next
    Else
      ' Nothing returned
      Call Response.Write("No data returned")
    End If
    

【讨论】:

  • 谢谢,很有帮助!
【解决方案2】:

看了几分钟,自从我使用经典 asp 以来已经很长时间了,但我确实看到了三件事:

  1. 在调用objCommandSec.Execute之前是否需要Open连接?
  2. 您能否尝试在循环中写出一个字符串文字,它完全不依赖于记录集...只是您实际上是在循环代码,因此请查看记录是否返回记录集。
  3. 您是否检查过 html 源代码,看看是否有格式错误的 html 隐藏了您的结果?我记得这种情况在经典 asp 循环中的表格中发生过几次,其中数据会以某种方式隐藏在两行之间,或者在错误位置的结束表格标记会结束表格,并且后面的行将不可见。

【讨论】:

    【解决方案3】:

    虽然这可能无法直接回答 OP 的问题,但它可能会帮助其他人寻找解决方案。

    最近我有一个维护工作,需要我修改正在运行的 ASP 经典代码中的某些内容(我已经很久没有写过代码了)。过程调用的编写方式与 OP 相同,而我过去不是这样做的。

    这是我过去使用的语法,我认为它比此处提供的其他解决方案更简洁。

    以下代码展示了如何读取输出参数、将参数传递给存储过程、将空值传递给参数、读取记录计数以及在 RecordSet 中迭代。

    dim conn, cmd, rs
    
    set conn = Server.CreateObject("ADODB.Connection")
    conn.Open "Driver={SQL Server};Server=servername;Uid=username;Pwd=password;Database=dbname;"
    
    set cmd = Server.CreateObject("ADODB.Command")
    cmd.ActiveConnection = conn
    cmd.CommandType = adCmdStoredProc
    cmd.CommandText = "procedurename"
    cmd.Parameters.Refresh
    cmd.Parameters("@nullparam") = null
    cmd.Parameters("@strparam") = "1"
    cmd.Parameters("@numparam") = 100
    
    set rs = Server.CreateObject ("ADODB.RecordSet")
    rs.CursorLocation = adUseClient ' to read recordcount'
    
    rs.open cmd, , adOpenStatic, adLockReadOnly
    
    Response.Write "Return Value: " & cmd.Parameters("@RETURN_VALUE") & "<br />"
    Response.Write "Record count: " & rs.RecordCount & "<br />"
    while not rs.EOF 
        ' or do whatever you like with data'
        Response.Write rs("colname") & "<br>"
        rs.MoveNext
    wend
    

    【讨论】:

    • 为什么更干净?首先,您使用ADODB.Recordset 打开它本身就是一种开销,您还打开一个单独的ADODB.Connection,这意味着您必须自己关闭它,而不是让ADODB.Command 为您处理它。我能看到的唯一真正好处是使用cmd.Parameters.Refresh,它仅适用于某些提供程序,但在使用 SQL Server 时是我的首选方法。
    • 连接是一种有限的资源,许多主机不允许每个页面实例与他们的 sql server 建立多个连接。打开一个连接使之成为可能。打开记录集是获取记录数,如果不需要记录数可以使用execute。关闭连接不是必需的,一旦呈现页面,IIS 将删除页面及其所有资源,包括连接。为了更干净,我指的是.Parameters.Append .CreateParameter和上面一行的点。
    • 有缺陷的论点你对 IIS 垃圾收集做出了太多假设,你永远不会让我相信在页面的生命周期内保持与数据库的连接是一个好主意。
    • 还请记住,.Refresh 带来了必须第二次往返服务器以获取参数定义的开销,因此不建议在生产环境中使用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-11-09
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多