【问题标题】:Why adParamOutput parameter doesn't contain a value after execute为什么执行后 adParamOutput 参数不包含值
【发布时间】:2011-11-08 21:40:37
【问题描述】:

我正在使用带有 ADO 的 ASP 经典,连接到 SQL Server 2008。

我继承了这段代码,它被严重破坏了,我将尝试重新创建相关部分。如果您需要更多详细信息或我遗漏了什么,请告诉我。

我创建一个命令并添加参数

oCmd.CommandType = adCmdStoredProc
...
oCmd.Parameters.Append oCmd.CreateParameter("@MyOutputParam", adInteger, adParamOutput, 4, NULL)

稍后,我从该命令打开一个阅读器:

oRS.Open oCmd, , adOpenForwardOnly, adLockReadOnly

之后,当 oRS 打开但在我读取任何记录或值之前,我尝试使用以下行中的 一个 获取输出参数的值:

val1 = oCmd("@MyOutputParam")
val2 = oCmd("@MyOutputParam").Value
val3 = oCmd.Parameters("@MyOutputParam").Value

所有三个(val1、val2、val3)变量都是 DB NULL。

我已确认在查询分析器中运行 SP 会为 @MyOutputParam 参数返回一个值:

declare @p33 int
exec usp_GetResultAndOutput 1, 2, 3, @p33 output
select @p33

这将返回一个包含我预期记录的记录集和第二个在一行中显示数字的记录集。

我什至尝试在尝试获取输出参数之前调用 rs.NextRecordset,但没有成功。

还有其他方法需要我处理输出参数吗?

我返回记录集和输出参数可以吗?

【问题讨论】:

    标签: sql-server asp-classic ado


    【解决方案1】:

    直到所有记录集被枚举到最后,才能检索输出参数。试想一下,客户端怎么可能在执行完成之前检索到参数的输出值呢? Execute() 调用只是开始执行,批处理继续在服务器上执行,直到返回所有结果。当客户端迭代由 SELECT 生成的结果集时,批处理正在执行该 SELECT。输出参数的值仅在批处理的end 时才知道。因此,在批处理完成之前不可能知道输出参数值,这意味着所有语句都已执行,这反过来要求客户端消耗(迭代)所有结果集。

    这是解析一组结果的规范形式:

    do
    {
      while (rs.MoveNext)
      {
        // do something with the row
      }
    } while (Not rs.NextRecordset Is Nothing)
    // now is safe to read the out param
    response.write oCmd("@MyOutput")
    

    【讨论】:

    • 我想这是有道理的,虽然似乎很多人想在结果集之前使用输出参数:dominicpettifer.co.uk/Blog/8/… 但即使有了这些知识,它对我也不起作用。我曾尝试在获取参数之前调用 .NextRecordset, .Close 或在遍历结果后才获取它。没有任何效果。还有其他想法吗?
    • 你确定你对 all 记录集进行了交互吗? NextRecordset 调用是否返回 false?在它返回 false 之前,您需要不断迭代。
    • 是的,我在 .Execute() 之后添加了一些测试代码,以使用 .MoveNext() 循环遍历每个记录。我尝试在那里获取参数,然后关闭记录集,然后获取参数或调用 .NextRecordset() 并获取参数。参数全部返回 NULL。
    • 查看我的编辑,您必须迭代所有结果集中的所有行,从您的解释中不清楚您是否这样做。
    • 在最后一个记录集上调用 NextRecordset() 之前,永远不要访问返回和输出参数(即使是出于调试目的!)。否则,在最后一次调用NextRecordset() 之后,它们将保持为空(vbEmpty!)并且不包含真实值!
    【解决方案2】:

    据我所知,唯一重要的是CursorLocation。只要将CursorLocation 设置为adUseClient (3),就可以在Execute 之后随时访问输出参数。以下任何一项都可以做到这一点

    oConn.CursorLocation = adUseClient
    

    oRs.CursorLocation = adUseClient
    

    这是在 SQL 2008 R2、Windows 7 上的 IIS/ASP 和 SQLOLEDB 提供程序上测试的。

    【讨论】:

    • 有没有办法为创建的记录集指定 adLockReadOnly 和 adOpenForwardOnly?我在看w3schools.com/ado/met_comm_execute.asp,它没有说有。
    • 这些是默认值,应该没问题。
    • 将其更改为 oCmd.Execute() 无效(执行后输出参数仍为空)
    • 在我调用 oRS.NextRecordset 以获取所有记录集之前,输出参数似乎不可用。但是如果我循环遍历第一个记录集中的每条记录,我仍然无法在 .NextRecordset 之后获得输出参数
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-03-12
    • 1970-01-01
    • 2020-11-27
    • 2018-02-18
    • 1970-01-01
    • 2018-10-02
    • 1970-01-01
    相关资源
    最近更新 更多