900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 使用 ADO.NET 访问 Oracle 9i 存储过程

使用 ADO.NET 访问 Oracle 9i 存储过程

时间:2022-08-02 11:53:05

相关推荐

使用 ADO.NET 访问 Oracle 9i 存储过程

使用 访问 Oracle 9i 存储过程 show toc 欢迎来到 MSDN > 数据

使用 访问 Oracle 9i 存储过程

发布日期: 5/28/ | 更新日期: 5/28/

Bill Hamilton

年 4 月

适用于:

Microsoft

Microsoft SQL Server

Microsoft .NET Oracle 提供程序

Microsoft .NET Framework 1.1 版

摘要:使用 Microsoft .NET 框架 1.1 中的 Microsoft .NET Oracle 提供程序访问 Oracle 存储过程和函数。(24 页打印页)

内容

本页内容

本文讨论了如何使用 访问 Oracle 存储过程(称为 SQL 编程块)和函数(返回单个值的编程块)。

您可以使用以下托管数据提供程序连接到 Oracle 数据库:Microsoft .NET Oracle 提供程序、OLE DB .NET 提供程序、ODBC .NET 数据提供程序以及 Oracle 的 提供程序。本文使用用于 Oracle 的 Microsoft?.NET 框架数据提供程序。使用 Oracle 数据提供程序或用于 OLE DB 的 Microsoft .NET 框架数据提供程序时可使用不同的功能。

Oracle .NET 数据提供程序随 .NET 框架 1.1 一起提供。如果您使用的是 .NET 框架 1.0,您将需要下载 .NET Managed Provider for Oracle。无论是哪个版本,数据提供程序类都位于System.Data.OracleClient命名空间中。

概述

PL/SQL 是 SQL 的 Oracle 实现。它与 Microsoft?SQL Server? 所使用的 T-SQL 类似,但也有一些不同之处,本文稍后对此进行了详细讨论。与 T-SQL 一样,PL/SQL 扩展了标准 SQL。PL/SQL 用于定义命名编程块,如存储过程、函数和触发器。

返回页首

可使用System.Data.OracleClient命名空间中类的子集来执行 Oracle 存储过程和函数。下表对这些类进行了说明:

返回页首

执行存储过程

执行 Oracle 存储过程与执行 SQL Server 存储过程类似。下面的步骤说明了如何执行 Oracle 存储过程和检索它返回的结果。

使用完连接后,不要忘记将其关闭。

conn.Open();cmd.ExecuteNonQuery();conn.Close();

如果您要使用DataAdapter来填充DataTable或DataSet,可以依靠DataAdapter来打开和关闭连接。

9.

处理结果。在我们的示例中,可在显示到控制台的输出参数中得到记录数:

Console.WriteLine(cmd.Parameters["reccount"].Value);

下面是在本示例中开发的用于执行存储过程和检索结果的代码:

OracleConnection conn = new OracleConnection("Data Source=oracledb;User Id=UserID;Password=Password;");OracleCommand cmd = new OracleCommand();cmd.Connection = conn;mandText = "COUNT_JOB_HISTORY";mandType = CommandType.StoredProcedure;cmd.Parameters.Add("reccount", OracleType.Number).Direction =ParameterDirection.Output;conn.Open();cmd.ExecuteNonQuery();conn.Close();Console.WriteLine(cmd.Parameters["reccount"].Value);

返回页首

不返回数据的存储过程

OracleCommand类的ExecuteOracleNonQuery()方法用于执行不返回任何行的 SQL 语句或存储过程。该方法返回一个int值,表示受UPDATE、INSERT和DELETE命令影响的行数;如果没有任何行受到影响,则返回-1。如果您所执行的INSERT、DELETE或UPDATE语句恰好影响一行,则该方法具有单个参数OracleString out rowid,该参数唯一标识 Oracle 数据库中受影响的行。可以使用该值来优化后续相关查询。

还可以使用OracleCommand类的ExecuteNonQuery()方法来执行不返回数据的存储过程,但您将无法获得上面介绍的唯一行标识符。

尽管上述命令都不会返回任何数据,但映射到参数的输出参数和返回值仍然使用数据进行填充。这使您可以使用上述任一命令从存储过程返回一个或多个标量值。

以下 Oracle 存储过程删除了由单个输入参数指定的员工的所有工作经历,并且不返回任何数据。

CREATE OR new PROCEDURE DELETE_JOB_HISTORY(p_employee_id NUMBER)ISBEGINDELETE FROM job_historyWHERE employee_id = p_employee_id;END DELETE_JOB_HISTORY;

以下代码运行了该存储过程。

// create the connectionOracleConnection conn = new OracleConnection("Data Source=oracledb;User Id=UserID;Password=Password;");// create the command for the stored procedureOracleCommand cmd = new OracleCommand();cmd.Connection = conn;mandText = "COUNT_JOB_HISTORY";mandType = CommandType.StoredProcedure;// add the parameter specifying the employee for whom to delete recordscmd.Parameters.Add("p_employee_id", OracleType.Number).Value = 102;OracleString rowId;// execute the stored procedureconn.Open();int rowsAffected = cmd.ExecuteNonQuery();conn.Close();Console.WriteLine("Rows affected: " + rowsAffected);

如果您尚未修改默认的 HR 安装,则 JOB_HISTORY 表中员工 102 的记录被删除,并且向控制台输出以下内容:

Rows affected: 1

访问返回值

RETURN语句立即将控制从存储过程返回到调用程序。Oracle 存储过程中的 RETURN 语句无法像在 T-SQL 中那样返回值。

Oracle 函数是计算并返回单个值的子程序。它们的结构类似于存储过程,不同之处在于它们总是具有必须返回值的 RETURN 子句。

下面是一个返回指定员工的电子邮件的函数:

CREATE OR new FUNCTION GET_EMPLOYEE_EMAIL (p_employee_id NUMBER)RETURN VARCHAR2IS p_email VARCHAR2(25);BEGINSELECT EMAIL INTO p_email FROM EMPLOYEESWHERE EMPLOYEE_ID = p_employee_id;RETURN p_email;END GET_EMPLOYEE_EMAIL;

执行函数的方式与执行存储过程的方式相同。可使用ParameterDirection.ReturnValue参数获得由函数返回的结果。以下代码显示了使用方法:

// create the connectionOracleConnection conn = new OracleConnection("Data Source=oracledb;User Id=UserID;Password=Password;");// create the command for the functionOracleCommand cmd = new OracleCommand();cmd.Connection = conn;mandText = "GET_EMPLOYEE_EMAIL";mandType = CommandType.StoredProcedure;// add the parameters, including the return parameter to retrieve// the return valuecmd.Parameters.Add("p_employee_id", OracleType.Number).Value = 101;cmd.Parameters.Add("p_email", OracleType.VarChar, 25).Direction =ParameterDirection.ReturnValue;// execute the functionconn.Open();cmd.ExecuteNonQuery();conn.Close();// output the resultConsole.WriteLine("Email address is: " + cmd.Parameters["p_email"].Value);

控制台输出显示了员工 101 的电子邮件地址。

Email address is: NKOCHHAR

返回页首

结果集与 REF CURSOR

可使用REF CURSOR数据类型来处理 Oracle 结果集。REF CURSOR是一个指向 PL/SQL 查询所返回的结果集的指针。与普通的游标不同,REF CURSOR是一个变量,它是对游标的引用,可以在执行时将其设置为指向不同的结果集。使用REF CURSOR输出参数可以将 Oracle 结构化程序的结果集传递回调用应用程序。通过在调用应用程序中定义OracleType.Cursor数据类型的输出参数,可以访问REF CURSOR所指向的结果集。在使用REF CURSOR的过程中,OracleConnection必须保持打开状态。

返回页首

PL/SQL 和 T-SQL 中的存储过程之间的一个重大差异是 PL/SQL 所使用的 Oracle 包 结构。在 T-SQL 中没有等效元素。包是在逻辑上相关的编程块(如存储过程和函数)的容器。它包含两个部分:

每个存储过程或函数的参数都出现在括号内,并且用逗号分隔。每个参数还根据需要用以下三个标识符中的一个进行标记:

每个参数也都被标记以指示数据类型。

以下包规范定义了四个过程,它们在 HR 架构的 LOCATIONS 表中创建、检索、更新和删除数据。

CREATE OR new PACKAGE CRUD_LOCATIONS ASTYPE T_CURSOR IS REF CURSOR;PROCEDURE GetLocations (cur_Locations OUT T_CURSOR);PROCEDURE UpdateLocations (p_location_id IN NUMBER,p_street_address IN VARCHAR2,p_postal_code IN VARCHAR2,p_city IN VARCHAR2,p_state_province IN VARCHAR2,p_country_id IN CHAR);PROCEDURE DeleteLocations (p_location_id IN NUMBER);PROCEDURE InsertLocations (p_location_id OUT NUMBER,p_street_address IN VARCHAR2,p_postal_code IN VARCHAR2,p_city IN VARCHAR2,p_state_province IN VARCHAR2,p_country_id IN CHAR);END CRUD_LOCATIONS;

以下代码摘自上述包规范的包正文,说明了GetLocations包中的第一个过程的实现细节:

CREATE OR new PACKAGE BODY CRUD_LOCATIONS ASPROCEDURE GetLocations (cur_Locations OUT T_CURSOR)ISBEGINOPEN cur_Locations FORSELECT * FROM LOCATIONS;END GetLocations;-- Implementation of other procedures ommitted.END CRUD_LOCATIONS;

返回页首

使用 DataReader

可以通过调用OracleCommand对象的ExecuteReader()方法来创建OracleDataReader。本节说明如何使用DataReader来访问由存储过程 SELECT_JOB_HISTORY 返回的结果集。以下为包规范:

CREATE OR new PACKAGE SELECT_JOB_HISTORY ASTYPE T_CURSOR IS REF CURSOR;PROCEDURE GetJobHistoryByEmployeeId(p_employee_id IN NUMBER,cur_JobHistory OUT T_CURSOR);END SELECT_JOB_HISTORY;

包正文定义了一个过程,该过程检索指定员工的工作经历的结果集,并将其作为REF CURSOR输出参数返回:

CREATE OR new PACKAGE BODY SELECT_JOB_HISTORY ASPROCEDURE GetJobHistoryByEmployeeId(p_employee_id IN NUMBER,cur_JobHistory OUT T_CURSOR)ISBEGINOPEN cur_JobHistory FORSELECT * FROM JOB_HISTORYWHERE employee_id = p_employee_id;END GetJobHistoryByEmployeeId;END SELECT_JOB_HISTORY;

以下代码执行该过程,根据结果集创建DataReader,并将DataReader的内容输出到控制台。

// create connectionOracleConnection conn = new OracleConnection("Data Source=oracledb;User Id=UserID;Password=Password;");// create the command for the stored procedureOracleCommand cmd = new OracleCommand();cmd.Connection = conn;mandText = "SELECT_JOB_HISTORY.GetJobHistoryByEmployeeId";mandType = CommandType.StoredProcedure;// add the parameters for the stored procedure including the REF CURSOR// to retrieve the result setcmd.Parameters.Add("p_employee_id", OracleType.Number).Value = 101;cmd.Parameters.Add("cur_JobHistory", OracleType.Cursor).Direction =ParameterDirection.Output;// open the connection and create the DataReaderconn.Open();OracleDataReader dr = cmd.ExecuteReader();// output the results and close the connection.while(dr.Read()){for(int i = 0; i < dr.FieldCount; i++)Console.Write(dr[i].ToString() + ";");Console.WriteLine();}conn.Close();

对于 HR 架构的默认安装,控制台输出显示了员工 101 的两个记录中每个记录的字段(用分号分隔):

101;9/21/1989 12:00:00 AM;10/27/1993 12:00:00 AM;AC_ACCOUNT;110;101;10/28/1993 12:00:00 AM;3/15/1997 12:00:00 AM;AC_MGR;110;

上述代码显示,包中的过程是使用包名称 (ELECT_JOB_HISTORY) 和过程的名称(在此情况下为GetJobHistoryByEmployeeId)指定的,二者之间用句点分隔。

代码还说明了如何定义结果集的REF CURSOR参数。请注意,数据类型为OracleType.Cursor,方向为ParameterDirection.Output。

还请注意,在访问REF CURSOR中的结果集的整个过程中,连接都保持打开状态。

如果包返回多个游标,则DataReader会按照您向参数集合中添加它们的顺序来访问这些游标,而不是按照它们在过程中出现的顺序来访问。可使用DataReader的NextResult()方法前进到下一个游标。

返回页首

返回单个值的存储过程

OracleCommand类的ExecuteOracleScalar()方法用于执行将单个值作为OracleType数据类型返回的 SQL 语句或存储过程。如果命令返回一个结果集,则该方法会返回第一行第一列的值。如果返回了REF CURSOR,而不是返回了REF CURSOR所指向的第一行第一列的值,则该方法会返回一个空引用。OracleCommand类的ExecuteScalar()方法类似于ExecuteOracleScalar()方法,只不过它将值作为 .NET 框架数据类型返回。

尽管如此,在使用 Oracle 存储过程时,这两个方法都没有用。Oracle 存储过程不能将值作为RETURN语句的一部分返回,而只能将其作为OUT参数返回。有关信息,请参阅不返回数据的存储过程一节。同时,除了通过REF CURSOR输出参数以外,您不能返回结果集。下一节将对此进行讨论。

您只能使用RETURN参数检索 Oracle 函数的返回值(如上一节所述),而不能使用ExecuteScalar方法之一进行检索。

返回页首

序列

Oracle 使用序列来生成唯一编号,而不是使用 SQL Server 所用的数据类型uniqueidentifier。无论是哪种情况,主要用途都是为主键列生成一系列唯一编号。与uniqueidentifier数据类型不同,序列是与将其用于主键值的一个或多个表无关的数据库对象。

Oracle 序列是原子对象,并且是一致的。也就是说,一旦您访问一个序列号,Oracle 将在处理下一个请求之前自动递增下一个编号,从而确保不会出现重复值。

可以使用CREATE SEQUENCE命令创建 Oracle 序列。该命令所带参数包括增量、起始值、最大值、循环和缓存。可使用NEXTVAL和CURRVAL关键字访问序列值。NEXTVAL 返回序列中的下一个编号,而 CURRVAL 提供对当前值的访问。HR 架构中的序列LOCATIONS_SEQ按如下方式定义:

CREATE SEQUENCE LOCATIONS_SEQINCREMENT BY 100START WITH 1MAXVALUE 9900MINVALUE 1NOCYCLE NOCACHENOORDER

大多数序列代码是不言自明的。NOCYCLE表示序列在达到最小值或最大值后将不再生成其他值。NOCACHE表示序列值在被请求之前不会进行分配;可使用预分配机制来改善性能。NOORDER表示在生成编号时,不能保证按照请求编号的顺序返回这些编号。

下面的代码显示了一个存储过程,该过程请求一个序列值,在向 LOCATIONS 表中插入记录时使用它设置主键值,然后在OUT参数中返回该主键值。

CREATE OR new PROCEDURE ADD_LOCATION (p_location_id OUT NUMBER,p_street_address IN VARCHAR2,p_postal_code IN VARCHAR2,p_city IN VARCHAR2,p_state_province IN VARCHAR2,p_country_id IN CHAR)ASBEGININSERT INTO LOCATIONS (LOCATION_ID,STREET_ADDRESS,POSTAL_CODE,CITY,STATE_PROVINCE,COUNTRY_ID)VALUES (LOCATIONS_SEQ.NEXTVAL,p_street_address,p_postal_code,p_city,p_state_province,p_country_id);SELECT LOCATIONS_SEQ.CURRVAL INTO p_location_id FROM DUAL;END ADD_LOCATION;

下面的代码调用该存储过程,以插入一个记录并检索返回的序列值。

// create the connectionOracleConnection conn = new OracleConnection("Data Source=oracledb;User Id=UserID;Password=Password;");// create the command for the stored procedureOracleCommand cmd = new OracleCommand();cmd.Connection = conn;mandText = "ADD_LOCATION";mandType = CommandType.StoredProcedure;// add the parameters for the stored procedure including the LOCATION_ID// sequence value that is returned in the output parameter p_location_idcmd.Parameters.Add("p_location_id", OracleType.Number).Direction =ParameterDirection.Output;cmd.Parameters.Add("p_street_address", OracleType.VarChar).Value ="123 Any Street";cmd.Parameters.Add("p_postal_code", OracleType.VarChar).Value = "33040";cmd.Parameters.Add("p_city", OracleType.VarChar).Value = "Key West";cmd.Parameters.Add("p_state_province", OracleType.VarChar).Value = "FL";cmd.Parameters.Add("p_country_id", OracleType.VarChar).Value = "US";// execute the command to add the recordsOracleString rowId;conn.Open();int rowsAffected = cmd.ExecuteOracleNonQuery(out rowId);conn.Close();// output the resultsConsole.WriteLine("Rows affected: " + rowsAffected);Console.WriteLine("Location ID: " +cmd.Parameters["p_location_id"].Value);

控制台显示一个记录被插入到该表中,同时还插入了该序列生成的主键值。

Rows affected: 1Location ID: 3300

返回页首

使用 DataAdapter 填充数据集

可使用REF CURSOR通过DataAdapter来填充DataSet。下面的代码利用了使用 DataReader 一节中定义的存储过程GetJobHistoryByEmployeeId,并用它在REF CURSOR输出参数中返回的结果集来填充DataSet。

以下是使用DataAdapter填充DataSet的代码:

// create the connectionOracleConnection conn = new OracleConnection("Data Source=oracledb;User Id=UserID;Password=Password;");// create the command for the stored procedureOracleCommand cmd = new OracleCommand();cmd.Connection = conn;mandText = "SELECT_JOB_HISTORY.GetJobHistoryByEmployeeId";mandType = CommandType.StoredProcedure;// add the parameters for the stored procedure including the REF CURSOR// to retrieve the result setcmd.Parameters.Add("p_employee_id", OracleType.Number).Value = 101;cmd.Parameters.Add("cur_JobHistory", OracleType.Cursor).Direction =ParameterDirection.Output;// createt the DataAdapter from the command and use it to fill the// DataSetOracleDataAdapter da = new OracleDataAdapter(cmd);DataSet ds = new DataSet();da.Fill(ds);// output the results.Console.WriteLine(ds.Tables[0].Rows.Count);

对于 HR 架构的默认安装,输出表明员工 101 有两个 JOB_HISTORY 记录。

返回页首

使用 DataAdapter 更新 Oracle

当您使用REF CURSOR参数填充DataSet时,不能简单地使用OracleDataAdapter的Update()方法。这是因为在执行存储过程时,Oracle 不能提供确定表名和列名所需的信息。要使用DataAdapter的Update()方法,您必须创建在基础表中更新、插入和删除记录的过程。该方法类似于在 SQL Server 中使用的方法。

本节说明如何生成一个可以处理所需的创建、检索、更新和删除操作的包,以便能够从 Oracle 数据库中检索 LOCATION 数据,也能够将对DataSet数据所做的不连续更改重新更新到 Oracle 数据库。包头如下所示:

CREATE OR new PACKAGE CRUD_LOCATIONS ASTYPE T_CURSOR IS REF CURSOR;PROCEDURE GetLocations (cur_Locations OUT T_CURSOR);PROCEDURE UpdateLocations (p_location_id IN NUMBER,p_street_address IN VARCHAR2,p_postal_code IN VARCHAR2,p_city IN VARCHAR2,p_state_province IN VARCHAR2,p_country_id IN CHAR);PROCEDURE DeleteLocations (p_location_id IN NUMBER);PROCEDURE InsertLocations (p_location_id OUT NUMBER,p_street_address IN VARCHAR2,p_postal_code IN VARCHAR2,p_city IN VARCHAR2,p_state_province IN VARCHAR2,p_country_id IN CHAR);END CRUD_LOCATIONS;

包正文如下所示:

CREATE OR new PACKAGE BODY CRUD_LOCATIONS AS-- retrieve all LOCATION recordsPROCEDURE GetLocations (cur_Locations OUT T_CURSOR)ISBEGINOPEN cur_Locations FORSELECT * FROM LOCATIONS;END GetLocations;-- update a LOCATION recordPROCEDURE UpdateLocations (p_location_id IN NUMBER,p_street_address IN VARCHAR2,p_postal_code IN VARCHAR2,p_city IN VARCHAR2,p_state_province IN VARCHAR2,p_country_id IN CHAR)ISBEGINUPDATE LOCATIONSSETSTREET_ADDRESS = p_street_address,POSTAL_CODE = p_postal_code,CITY = p_city,STATE_PROVINCE = p_state_province,COUNTRY_ID = p_country_idWHERELOCATION_ID = p_location_id; END UpdateLocations;-- delete a LOCATION recordPROCEDURE DeleteLocations (p_location_id IN NUMBER)ISBEGINDELETE FROM LOCATIONSWHERE LOCATION_ID = p_location_id;END DeleteLocations;-- insert a LOCATION recordPROCEDURE InsertLocations(p_location_id OUT NUMBER,p_street_address IN VARCHAR2,p_postal_code IN VARCHAR2,p_city IN VARCHAR2,p_state_province IN VARCHAR2,p_country_id IN CHAR)ASBEGININSERT INTO LOCATIONS (LOCATION_ID,STREET_ADDRESS,POSTAL_CODE,CITY,STATE_PROVINCE,COUNTRY_ID)VALUES (LOCATIONS_SEQ.NEXTVAL,p_street_address,p_postal_code,p_city,p_state_province,p_country_id);SELECT LOCATIONS_SEQ.CURRVAL INTO p_location_id FROM DUAL;END InsertLocations;END CRUD_LOCATIONS;

下面的代码定义了一个DataAdapter,从而使用上述包中定义的过程来创建、检索、更新和删除支持DataAdapter的数据。DataAdapter既可用来将数据检索到DataSet中,也可用来将对DataSet所做的更改更新到 Oracle 数据库中。

// define the connection stringString connString = "Data Source=oracledb;User Id=UserID;Password=Password;";// create the data adapterOracleDataAdapter da = new OracleDataAdapter();// define the select command for the data adapterOracleCommand selectCommand =new OracleCommand("CRUD_LOCATIONS.GetLocations",new OracleConnection(connString));mandType = CommandType.StoredProcedure;selectCommand.Parameters.Add("cur_Locations",OracleType.Cursor).Direction = ParameterDirection.Output;da.SelectCommand = selectCommand;// define the udpate command for the data adapterOracleCommand updateCommand =new OracleCommand("CRUD_LOCATIONS.UpdateLocations",new OracleConnection(connString));mandType = CommandType.StoredProcedure;updateCommand.Parameters.Add("p_location_id", OracleType.Number, 4,"LOCATION_ID");updateCommand.Parameters.Add("p_street_address", OracleType.VarChar, 40,"STREET_ADDRESS");updateCommand.Parameters.Add("p_postal_code", OracleType.VarChar, 12,"POSTAL_CODE");updateCommand.Parameters.Add("p_city", OracleType.VarChar, 30, "CITY");updateCommand.Parameters.Add("p_state_province", OracleType.VarChar, 25,"STATE_PROVINCE");updateCommand.Parameters.Add("p_country_id", OracleType.Char, 2,"COUNTRY_ID");da.UpdateCommand = updateCommand;// define the delete command for the data adapterOracleCommand deleteCommand =new OracleCommand("CRUD_LOCATIONS.DeleteLocations",new OracleConnection(connString));mandType = CommandType.StoredProcedure;deleteCommand.Parameters.Add("p_location_id", OracleType.Number, 4,"LOCATION_ID");da.DeleteCommand = deleteCommand;OracleCommand insertCommand =new OracleCommand("CRUD_LOCATIONS.InsertLocations",new OracleConnection(connString));mandType = CommandType.StoredProcedure;insertCommand.Parameters.Add("p_location_id", OracleType.Number, 4,"LOCATION_ID");insertCommand.Parameters.Add("p_street_address", OracleType.VarChar, 40,"STREET_ADDRESS");insertCommand.Parameters.Add("p_postal_code", OracleType.VarChar, 12,"POSTAL_CODE");insertCommand.Parameters.Add("p_city", OracleType.VarChar, 30, "CITY");insertCommand.Parameters.Add("p_state_province", OracleType.VarChar, 25,"STATE_PROVINCE");insertCommand.Parameters.Add("p_country_id", OracleType.Char, 2,"COUNTRY_ID");da.InsertCommand = insertCommand;// define a DataTable and fill it using the data adapterDataTable dt = new DataTable();da.Fill(dt);// ... do work that adds, edits, updates, or deletes records in the table// call the Update() method of the data adapter to update the Oracle// database with changes made to the datada.Update(dt);

返回页首

使用多个结果集

Oracle 不支持批量查询,因此无法从一个命令返回多个结果集。使用存储过程时,返回多个结果集类似于返回单个结果集;必须使用REF CURSOR输出参数。要返回多个结果集,请使用多个REF CURSOR输出参数。

以下是返回两个结果集(全部 EMPLOYEES 和 JOBS 记录)的包规范:

CREATE OR new PACKAGE SELECT_EMPLOYEES_JOBS ASTYPE T_CURSOR IS REF CURSOR;PROCEDURE GetEmployeesAndJobs (cur_Employees OUT T_CURSOR, cur_Jobs OUT T_CURSOR);END SELECT_EMPLOYEES_JOBS;包正文如下所示:CREATE OR new PACKAGE BODY SELECT_EMPLOYEES_JOBS ASPROCEDURE GetEmployeesAndJobs(cur_Employees OUT T_CURSOR,cur_Jobs OUT T_CURSOR)ISBEGIN-- return all EMPLOYEES recordsOPEN cur_Employees FORSELECT * FROM Employees;-- return all JOBS recordsOPEN cur_Jobs FORSELECT * FROM Jobs;END GetEmployeesAndJobs;END SELECT_EMPLOYEES_JOBS;

以下代码显示了如何使用从上述包中返回的两个结果集来填充DataSet中的两个相关表:

// create the connectionOracleConnection conn = new OracleConnection("Data Source=oracledb;User Id=UserID;Password=Password;");// define the command for the stored procedureOracleCommand cmd = new OracleCommand();cmd.Connection = conn;mandText = "SELECT_EMPLOYEES_JOBS.GetEmployeesAndJobs";// add the parameters including the two REF CURSOR types to retrieve// the two result setscmd.Parameters.Add("cur_Employees", OracleType.Cursor).Direction =ParameterDirection.Output;cmd.Parameters.Add("cur_Jobs", OracleType.Cursor).Direction =ParameterDirection.Output;mandType = CommandType.StoredProcedure;// create the DataAdapter and map tablesOracleDataAdapter da = new OracleDataAdapter(cmd);da.TableMappings.Add("Table", "EMPLOYEES");da.TableMappings.Add("Table1", "JOBS");// create and fill the DataSetDataSet ds = new DataSet();da.Fill(ds);// create a relationds.Relations.Add("EMPLOYEES_JOBS_RELATION",ds.Tables["JOBS"].Columns["JOB_ID"],ds.Tables["EMPLOYEES"].Columns["JOB_ID"]);// output the second employee (zero-based array) and job title// based on the relationConsole.WriteLine("Employee ID: " +ds.Tables["EMPLOYEES"].Rows[1]["EMPLOYEE_ID"] +"; Job Title: " +ds.Tables["EMPLOYEES"].Rows[1].GetParentRow("EMPLOYEES_JOBS_RELATION")["JOB_TITLE"]);

控制台输出显示了第二个员工的职务:

Employee ID: 101; Job Title: Administration Vice President

返回页首

小结

通过 Oracle .NET 数据提供程序,可以方便地执行存储过程以及访问返回值(无论返回值是一个还是多个标量值或结果集)。可以将 Oracle 过程与OracleDataAdapter结合使用,从而填充DataSet、处理不连续的数据以及以后将更改更新到 Oracle 数据库。

Oracle 过程与 Microsoft SQL Server 存储过程之间的主要区别是:Oracle 过程必须将值作为输出参数返回,并且必须使用输出参数将结果集作为REF CURSOR对象返回给调用程序。

返回页首

相关书籍

Cookbook

in a Nutshell

Bill Hamilton是一位软件设计师,他专门致力于使用Microsoft .NET和J2EE技术来设计、开发和实现分布式应用程序。作为早期的技术采用者,他经常评估、推荐新技术并且帮助他的客户有效地使用新技术。Bill已经撰写了两部有关的著作。

posted on -05-30 14:18cowbird 阅读(...) 评论(...) 编辑 收藏

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。