从存储过程,返回OUT参数和OUT游标和解析结果(Oracle)

问题:是否可以使用OUT返回:

两者:一个变量和一个游标,从我的代码下面?


我在SqlDB上看到了类似的问题,但经过一段很长的搜索后发现没有针对OracleDB的解决方案。

在PLSQL中:

CREATE OR REPLACE PROCEDURE SPGETRESULTANDSETFLAG ( pFilter VARCHAR2, pMaxRowCount VARCHAR2, pTableID RAW, myFlag OUT NUMBER, myCursor OUT types.cursorType ) AS BEGIN Declare CountQuery VARCHAR(20000) := ''; DataQuery VARCHAR(20000) := ''; ResultingRows NUMBER := -1; Begin myFlag := -1; CountQuery := 'SELECT COUNT(*) FROM ' || F_GET_TABLENAME_FROM_ID(PTABLEID => pTableID) || ' WHERE ' || pFilter; EXECUTE IMMEDIATE CountQuery INTO ResultingRows; --Get the Return Value if( pMaxRowCount > ResultingRows ) then myFlag := 1; end if; DataQuery := 'SELECT * FROM ' || F_GET_TABLENAME_FROM_ID(PTABLEID => pTableID) || ' WHERE ' || pFilter; --Get the Return Cursor Open myCursor for DataQuery; End; END SPGETRESULTANDSETFLAG; 

在代码背后..

 Database db = DBSingleton.GetInstance(); using (DbCommand command = db.GetStoredProcCommand(spName)) { //The three Add In Parameters... & then the Add out Parameter as below db.AddOutParameter(command, "myFlag", System.Data.DbType.Int32, LocVariable ); using ( IDataReader reader = db.ExecuteReader(command)) { //Loop through cursor values & store them in code behind class-obj(s) } } 

我认为这是不可能的,因为我如何读取值和光标,因为..

如果只有标志param out然后我会使用db.ExecuteNonQuery(..)如果只有光标,那么我将使用db.ExecuteReader(..)

是的,可以有多个输出参数。 这是我用来在c#中调用Oracle存储过程的示例:

 OracleParameter op = null; OracleDataReader dr = null; /* custom code here. Yours would look a little different */ OracleCommand cmd = (OracleCommand) this.FactoryCache.Connection.CreateCommand(); cmd.CommandText = "pkg_prov_index.getNextPanel"; cmd.CommandType = CommandType.StoredProcedure; op = new OracleParameter("pCurrentPanelId", OracleType.VarChar); op.Direction = ParameterDirection.Input; op.Value = masterProviderIndex.CurrentPanelId; cmd.Parameters.Add(op); op = new OracleParameter("pRefCursor", OracleType.Cursor); op.Direction = ParameterDirection.Output; cmd.Parameters.Add(op); op = new OracleParameter("pReturnCode", OracleType.Number); op.Direction = ParameterDirection.Output; op.Size = 5; cmd.Parameters.Add(op); op = new OracleParameter("pReturnMessage", OracleType.VarChar); op.Direction = ParameterDirection.Output; op.Size = 4000; cmd.Parameters.Add(op); cmd.ExecuteNonQuery(); returnCode = Convert.ToInt16(cmd.Parameters[2].Value); returnMessage = cmd.Parameters[3].Value.ToString(); dr = (OracleDataReader) cmd.Parameters[1].Value; while (dr.Read()) { } 

谢谢你的回答

我非常渴望得到一个工作结果并以某种方式遇到一个解决方案,并在阅读了一下后发现它为什么有效:


Oracle存储过程没有变化。


代码背后 – 改变如下:

 Database db = DBSingleton.GetInstance(); using (DbCommand command = db.GetStoredProcCommand(spName)) { //The three Add In Parameters... & then the Add out Parameter as below db.AddOutParameter(command, "myFlag", System.Data.DbType.Int32, LocVariable ); using ( IDataReader reader = db.ExecuteReader(command)) { //Loop through cursor values & store them in code behind class-obj(s) //The reader must be closed before trying to get the "OUT parameter" reader.Close(); //Only after reader is closed will any parameter result be assigned //So now we can get the parameter value. //if reader was not closed then OUT parameter value will remain null //Getting the parameter must be done within this code block //I could not get it to work outside this code block  result = (typecast)command.Parameters["OUT_parameter_name"]; } } //I USED THIS APPROACH TO RETURN MULTIPLE PARAMETERS ALONG WITH THE CURSOR READ 
  using (myCmd) { myCmd.Parameters.AddWithValue("p_session_id", sessionId); myCmd.Parameters.AddWithValue("p_user", SessionHelper.UserEmailID); OracleParameter retval = new OracleParameter("p_status", OracleType.NVarChar, 35); retval.Direction = ParameterDirection.Output; myCmd.Parameters.Add(retval); OracleParameter retval2 = new OracleParameter("p_status_dtl", OracleType.NVarChar, 300); retval2.Direction = ParameterDirection.Output; myCmd.Parameters.Add(retval2); OracleParameter retval3 = new OracleParameter("p_output", OracleType.Cursor); retval3.Direction = ParameterDirection.Output; myCmd.Parameters.Add(retval3); myCmd.ExecuteNonQuery(); status = myCmd.Parameters["p_status"].Value.ToString(); statusDetail = myCmd.Parameters["p_status_dtl"].Value.ToString(); using (OracleDataReader reader = (OracleDataReader)myCmd.Parameters["p_output"].Value) { outPutDt.Load(reader); } } 

}

我不知道你使用哪个库进行Oracle访问…但通常可以将光标声明并将参数声明为参数,并使用带有anoynmous PL / SQL块的ExecuteNonQuery(在其中调用存储)程序)…例如使用Devart dotconnect组件这是可能的……(不是附属,只是一个快乐的客户)

可以考虑在您的过程中替换重复查询。 例如:

 CREATE OR REPLACE PROCEDURE SPGETRESULTANDSETFLAG ( pFilter VARCHAR2, pTableID RAW, myCursor OUT types.cursorType ) AS DataQuery VARCHAR(20000) := ''; BEGIN DataQuery := 'SELECT COUNT(*) OVER () AS TheCount, T.* FROM ' || F_GET_TABLENAME_FROM_ID(PTABLEID => pTableID) || ' AS T WHERE ' || pFilter; --Get the Return Cursor Open myCursor for DataQuery; END SPGETRESULTANDSETFLAG; 

这样,您不必两次查询表,您在结果集的每一行中都有计数。 您也可以删除处理max rowcount的参数,并通过获取一行来检查调用例程中的计数值。

只是另一种想法……