如何调用返回引用游标的Oracle存储过程
Posted
技术标签:
【中文标题】如何调用返回引用游标的Oracle存储过程【英文标题】:How to call Oracle stored procedure which returns ref cursor 【发布时间】:2013-10-18 04:00:52 【问题描述】:我正在尝试调用返回 ref 游标的 Oracle 存储过程,并且我需要从返回的数据生成树视图。我是新手,我有两个问题。
第一个问题是我无法调用该程序。我收到此错误:“调用 'OBJECT_HIERARCHY' 时参数的数量或类型错误”
我的第二个问题是我不明白当这个过程返回一个引用游标值时我将如何获取该数据?该表中有超过 5000 条记录,我没有得到该数据,而是一个参考游标值。有人可以解释我如何使用参考光标值获取该数据。我没有使用 Oracle 的经验。
这是oracle中的过程定义:
CREATE OR REPLACE PROCEDURE SAD.object_hierarchy
(nAppId IN NUMBER,
nParentId IN NUMBER DEFAULT -1,
o_cRefCursor OUT SYS_REFCURSOR)
IS
BEGIN
IF NOT o_cRefCursor%ISOPEN THEN
OPEN o_cRefCursor FOR
SELECT
h.PARENT_ID, h.CHILD_ID, h.H_LEVEL,
o.OBJECT_IDENTIFIER, o.OBJECT_TYPE_ID
FROM
(
SELECT
PARENT_ID, CHILD_ID, LEVEL AS H_LEVEL
FROM OBJECT_RELATIONSHIPS
START WITH PARENT_ID = nParentId --> -1 --= 60170
CONNECT BY PRIOR CHILD_ID = PARENT_ID
) h
INNER JOIN
OBJECTS o
ON
o.OBJECT_ID = h.CHILD_ID AND
O.APPLICATION_ID = nAppId;
END IF;
END object_hierarchy;
这些是表字段定义
Column Name Data Type
OBJECT_REL_ID NUMBER (14)
PARENT_ID NUMBER (14)
CHILD_ID NUMBER (14)
OBJECT_IDENTIFIER VARCHAR2 (255 Byte)
OBJECT_TYPE_ID VARCHAR2 (5 Byte)
这是我返回错误的代码:
string oradb = "Data Source=(DESCRIPTION="
+ "(ADDRESS=(PROTOCOL=TCP)(HOST=tnt33)(PORT=1521))"
+ "(CONNECT_DATA=(SERVICE_NAME=ORCL)));"
+ "User Id=xxx;Password=xxxxx;";
OracleConnection con = new OracleConnection(oradb);
try
con.Open();
OracleCommand cmd = new OracleCommand();
cmd.Connection = con;
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "SAD.object_hierarchy";
cmd.Parameters.Add("nAppId", OracleDbType.Int16).Value = 1;
OracleParameter oraP = new OracleParameter();
oraP.OracleDbType = OracleDbType.RefCursor;
oraP.Direction = System.Data.ParameterDirection.Output;
cmd.Parameters.Add(oraP);
OracleDataReader reader = cmd.ExecuteReader();
while (reader.Read())
reader.Close();
catch (Exception ex)
con.Close();
有人可以帮我解释一下为什么我的代码会返回此错误:“调用 'OBJECT_HIERARCHY' 时参数的数量或类型错误”
【问题讨论】:
【参考方案1】:例子:
string connStr = "Data Source=...";
DataSet dataset = new DataSet();
string connStr = ConfigurationManager.ConnectionStrings["OracleConn"].ToString();
using (OracleConnection objConn = new OracleConnection(connStr))
OracleCommand cmd = new OracleCommand();
cmd.Connection = objConn;
cmd.CommandText = "Oracle_PkrName.Stored_Proc_Name";
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("Emp_id", OracleType.Int32).Value = 3; // Input id
cmd.Parameters.Add("Emp_out", OracleType.Cursor).Direction = ParameterDirection.Output;
try
objConn.Open();
cmd.ExecuteNonQuery();
OracleDataAdapter da = new OracleDataAdapter(cmd);
da.Fill(dataset);
catch (Exception ex)
System.Console.WriteLine("Exception: 0", ex.ToString());
objConn.Close();
【讨论】:
对于使用 OracleManagedDataAccess 的最新版本,必须使用OracleDbType.RefCursor
而不是 OracleType.Cursor
。
@ΩmegaMan:当我将 OracleDbType.RefCursor 的方向更改为 ReturnValue 而不是 Output 时,我得到一个异常“错误的数字或类型或参数”......这是为什么?
@Nina 将输出光标的顺序从现在的位置更改为第一个或最后一个位置。我在使用它时不得不玩弄它。
@ΩmegaMan:我将光标参数的顺序(在我的情况下是返回值)更改为第一个,现在它可以工作了。谢谢【参考方案2】:
如果您要提供OUT
,则还需要提供nParentId
,因为.NET 在将语句发送到服务器时不会命名这些参数。
cmd.Parameters.Add("nParentId", OracleDbType.Int16).Value = -1;
【讨论】:
终于成功了。谢谢你。我编辑了我的第一篇文章以更正代码 我已经回滚了对您帖子的编辑,因为我正在阅读您的问题并且无法弄清楚出了什么问题。让问题保持原样。以上是关于如何调用返回引用游标的Oracle存储过程的主要内容,如果未能解决你的问题,请参考以下文章