ORACLE HANDBOOK系列之四:ODP.NET与复杂的PL/SQL数据类型(四)

2014-11-24 14:40:45 · 作者: · 浏览: 3
or)

引用游标作为输出参数的情况十分常见。相较于MS SQL Server,Oracle存储过程无法直接返回结果集,而需要借助REF Cursor。REF Cursor实际上是指向服务器内存的指针,也就是说客户端调用获取的是一个指针,它指向服务器内存中的结果集数据。

虽然可能令熟悉MS SQL Server平台的开发者困惑,但是使用REF Cursor带来两个明显的好处:1)它可以延迟数据的交付,客户端获取的只是指针,数据只有在被请求时才传递;2)使用REF Cursor在存储过程之间传递结果集,可以最小化对性能影响,毕竟传递的只是指针而不是真实数据。

(使用DataReader)

cmd.CommandText = "pkg_odp_dotnet.proc_ref_cursor";
cmd.CommandType = CommandType.StoredProcedure;
//
OracleParameter op = new OracleParameter();
op.ParameterName = "p_ref_cursor";
op.Direction = ParameterDirection.Output;
op.OracleDbType = OracleDbType.RefCursor;
cmd.Parameters.Add(op);
OracleDataReader odr = cmd.ExecuteReader();
//
if (odr.HasRows)
{
while (odr.Read())
{
string s = odr.GetDecimal(odr.GetOrdinal("employee_id")) + " "
+ odr.GetString(odr.GetOrdinal("first_name")) + " "
+ odr.GetString(odr.GetOrdinal("last_name"));
Console.WriteLine(s);
}
}

(使用DataAdapter)

cmd.CommandText = "pkg_odp_dotnet.proc_ref_cursor";
cmd.CommandType = CommandType.StoredProcedure;
//
OracleParameter op = new OracleParameter();
op.ParameterName = "p_ref_cursor";
op.Direction = ParameterDirection.Output;
op.OracleDbType = OracleDbType.RefCursor;
cmd.Parameters.Add(op);
OracleDataAdapter oda = new OracleDataAdapter(cmd);
DataSet ds = new DataSet();
oda.Fill(ds);
//
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
string s = ds.Tables[0].Rows[i]["employee_id"] + " "
+ ds.Tables[0].Rows[i]["first_name"] + " "
+ ds.Tables[0].Rows[i]["last_name"];
Console.WriteLine(s);
}

注意上面的Tables[0],如果有多个输出参数是REF Cursor,则可以使用Tables[0]、Tables[1],以此类推。DataReader似乎无法在有多个输出的REF Cursor有情况下使用。

方便起见,可以使用Oracle预定义的SYS_REFCURSOR,这样可以省去TYPE定义。在用法上与自定义的REF Cursor相同,就不再举具体的实例了。


2.关联数组(Associative array)

关于PL/SQL中的集合类型,已经在上一篇文章《ORACLE HANDBOOK系统之三:PL/SQL中的集合类型(COLLECTIONS IN PL/SQL)》中介绍了(http://www.cnblogs.com/KissKnife/archive/2011/04/07/2008158.html),这里介绍C#与Oracle交互时如何使用关联数组。

(作为输入参数)

cmd.CommandText = "pkg_odp_dotnet.proc_asso_array_num_in";
cmd.CommandType = CommandType.StoredProcedure;
//
OracleParameter op = new OracleParameter();
op.ParameterName = "p_asso_array_num";
op.Direction = ParameterDirection.Input;
op.OracleDbType = OracleDbType.Decimal;
//
op.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
op.Value = new decimal[] { 100, 101, 102 };
//
cmd.Parameters.Add(op);
cmd.ExecuteNonQuery();

相应的,如果定义的Associative array的元素是Varchar2,则OracleParameter.OracleDbType就是OracleDbType.Varchar2,为OracleParameter.value赋值要使用string[]。

(作为输出参数)

using Oracle.DataAccess.Types;

cmd.CommandText = "pkg_odp_dotnet.proc_asso_array_str_out";
cmd.CommandType = CommandType.StoredProcedure;
//
OracleParameter op = new OracleParameter();
op.ParameterName = "p_asso_array_str";
op.Direction = ParameterDirection.Output;
op.OracleDbType = OracleDbType.Varchar2;
//
op.CollectionType = OracleCollectionType.PLSQLAssociativeArray;
//
op.Size = 12;
int[] iArray = new int[op.Size];
for (int i = 0; i < iArray.Length; i++)
{
iArray[i] = 25;
}
op.ArrayBindSize = iArray;
//
cmd.Parameters.Add(op);
cmd.ExecuteNonQuery();
//
OracleString[] osArray = (OracleString[])op.Value;
for (int i = 0; i <= osArray.GetUpperBound(0); i++)
{
Console.WriteLine(osArray[i].Value + ",");
}

OracleParameter.Size,如果给定的Size比实际查询所得的行数小,则会报ORA-06513错误,所以如果无法确定实际返回的