问题
I am using ASP classic with ADO, connecting to SQL Server 2008.
I inherited this code and it is so mangled that I will try to recreate the relevant parts. If you need more detail or I left something out, please let me know.
I create a command and add parameters
oCmd.CommandType = adCmdStoredProc
...
oCmd.Parameters.Append oCmd.CreateParameter("@MyOutputParam", adInteger, adParamOutput, 4, NULL)
Later, I open a reader from that command:
oRS.Open oCmd, , adOpenForwardOnly, adLockReadOnly
After that, while oRS is open but before I've read any records or values, I try to get the output parameter's value using one of the lines below:
val1 = oCmd("@MyOutputParam")
val2 = oCmd("@MyOutputParam").Value
val3 = oCmd.Parameters("@MyOutputParam").Value
All three (val1, val2, val3) variables are DB NULL.
I have confirmed that running the SP in query analyzer returns a value to the @MyOutputParam parameter:
declare @p33 int
exec usp_GetResultAndOutput 1, 2, 3, @p33 output
select @p33
That returns a recordset of my expected records and a second recordset showing a number in a single row.
I've even tried calling rs.NextRecordset before attempting to get the output parameter and that didn't work.
Is there some other way that I need to be handling Output parameters?
Is it okay that I am returning a recordset and output parameters?
回答1:
Output parameters cannot be retrieved until all the recordsets are enumerated until the end. Just think, how could the client possibly retrieve the output value of a parameter before the execution finishes? The Execute() call is simply starting the execution, the batch continues to execute on the server until all results are returned. While a client is iterating over a resultset produced by a SELECT the batch is executing that SELECT. The value of the output parameter is known only at the end of the batch. Therefore is not possible to know the output parameter value until the batch finished, which implies that all statements have executed, which in turn requires that all resultsets were consumed (iterated) by the client.
This is the canonical form of parsing a set of results:
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")
回答2:
As far as I can test the only thing that matters this is the CursorLocation. As long as the CursorLocation is set to adUseClient (3), the output parameters can be accessed anytime after the Execute. Any of the following do that
oConn.CursorLocation = adUseClient
or
oRs.CursorLocation = adUseClient
This is tested on SQL 2008 R2, IIS/ASP on Windows 7 and with SQLOLEDB provider.
来源:https://stackoverflow.com/questions/8057433/why-adparamoutput-parameter-doesnt-contain-a-value-after-execute