c#调用oracle存储过程返回数据集

2008-12-20 10:59:57|  分类: net|字号 订阅

 

CREATE OR REPLACE PACKAGE pkg_tableType
IS
     type Tabletype is ref cursor;
     PROCEDURE SP_CPZD
      (
      CPNO IN VARCHAR2,
      STATUS IN VARCHAR2,
      t_sql out Tabletype
      );
END;
CREATE OR REPLACE package BODY pkg_tableType
is
PROCEDURE SP_CPZD
(
CPNO IN VARCHAR2,
STATUS IN VARCHAR2,
t_sql out Tabletype
)
IS
BEGIN
        OPEN t_sql FOR

select *  from ball b where b.no=CPNO  and  b.type =STATUS ;

END SP_CPZD;
END pkg_tableType;

#region 存储过程操作
     /// <summary>
  /// 执行存储过程
  /// </summary>
  /// <param name="storedProcName">存储过程名</param>
  /// <param name="parameters">存储过程参数</param>
  /// <returns>OracleDataReader</returns>
  public static OracleDataReader RunProcedure(string storedProcName, IDataParameter[] parameters )
  {
   OracleConnection connection = new OracleConnection(connectionString);
   OracleDataReader returnReader;
   connection.Open();
   OracleCommand command = BuildQueryCommand( connection,storedProcName, parameters );
   command.CommandType = CommandType.StoredProcedure;
   returnReader = command.ExecuteReader();    
   return returnReader;   
  }
  /// <summary>
  /// 执行存储过程
  /// </summary>
  /// <param name="storedProcName">存储过程名</param>
  /// <param name="parameters">存储过程参数</param>
  /// <param name="tableName">DataSet结果中的表名</param>
  /// <returns>DataSet</returns>
  public static DataSet RunProcedure(string storedProcName, IDataParameter[] parameters, string tableName )
  {
   using (OracleConnection connection = new OracleConnection(connectionString))
   {
    DataSet dataSet = new DataSet();
    connection.Open();
    OracleDataAdapter sqlDA = new OracleDataAdapter();
    sqlDA.SelectCommand = BuildQueryCommand(connection, storedProcName, parameters );
    sqlDA.Fill(dataSet, tableName );
    connection.Close();
    return dataSet;
   }
  }  
  /// <summary>
  /// 构建 OracleCommand 对象(用来返回一个结果集,而不是一个整数值)
  /// </summary>
  /// <param name="connection">数据库连接</param>
  /// <param name="storedProcName">存储过程名</param>
  /// <param name="parameters">存储过程参数</param>
  /// <returns>OracleCommand</returns>
  private static OracleCommand BuildQueryCommand(OracleConnection connection,string storedProcName, IDataParameter[] parameters)
  {   
   OracleCommand command = new OracleCommand(storedProcName, connection );
   command.CommandType = CommandType.StoredProcedure;
   foreach (OracleParameter parameter in parameters)
   {
    command.Parameters.Add( parameter );
   }
   return command;   
  }
  /// <summary>
  /// 执行存储过程,返回影响的行数  
  /// </summary>
  /// <param name="storedProcName">存储过程名</param>
  /// <param name="parameters">存储过程参数</param>
  /// <param name="rowsAffected">影响的行数</param>
  /// <returns></returns>
  public static int RunProcedure(string storedProcName, IDataParameter[] parameters, out int rowsAffected )
  {
   using (OracleConnection connection = new OracleConnection(connectionString))
   {
    int result;
    connection.Open();
    OracleCommand command = BuildIntCommand(connection,storedProcName, parameters );
    rowsAffected = command.ExecuteNonQuery();
    result = (int)command.Parameters["ReturnValue"].Value;
    //Connection.Close();
    return result;
   }
  }
  /// <summary>
  /// 创建 OracleCommand 对象实例(用来返回一个整数值) 
  /// </summary>
  /// <param name="storedProcName">存储过程名</param>
  /// <param name="parameters">存储过程参数</param>
  /// <returns>OracleCommand 对象实例</returns>
  private static OracleCommand BuildIntCommand(OracleConnection connection,string storedProcName, IDataParameter[] parameters)
  {
   OracleCommand command = BuildQueryCommand(connection,storedProcName, parameters );
   command.Parameters.Add( new OracleParameter ( "ReturnValue",
    OracleType.Int32,4,ParameterDirection.ReturnValue,
    false,0,0,string.Empty,DataRowVersion.Default,null ));
   return command;
  }

#endregion

public DataSet GetCPResult(string s_aN_CPNO)
        {
            OracleParameter[] parameter = { 
                new OracleParameter("CPNO",OracleType.VarChar,100),
                new OracleParameter("STATUS",OracleType.VarChar,100),//注意:这里参数名称前面都不能加":"
                new OracleParameter("t_sql", OracleType.Cursor)};
            parameter[0].Value = s_aN_CPNO;
            parameter[1].Value = "3";
            parameter[2].Direction = System.Data.ParameterDirection.Output;
            return RunProcedure("pkg_tabletype.sp_cpzd", parameter, "ds");
        }

-==-------------------------------------------------=========================

随笔- 125  文章- 0  评论- 7 

--通过oracle存储过程返回数据集

==========
http://www.cnblogs.com/xiaomi7732/archive/2008/01/01/1022083.html
======
Microsoft Enterprise Library中所带的Data Access Application Block(以下简称DAAB),对ADO.NET进行了一次封装,为数据库访问带来了极大的便利,尤其是与SQL Server配合使用,可谓得心应手。但是,其访问Oracle数据库,特别是使用Oracle的存储过程时,大家时常会遇到一些问题,例如:怎么通过Oracle的存储过程,来返回一个数据集?既然它们的访问方式有所不同,怎么才能让程序既适用于SQL Server又适用于Oracle?小弟有幸在项目中遇到了此种需求,并且找到了解决方案,拿出来与大家讨论。
说到Oracle中存储过程返回数据集与SQL有何不同,就要说到包的概念,因为SQL Server中不存在相对应的概念。网上有许多相关的文章,在此不再赘述。另一个不同点,就是SQL Server的存储过程中,执行一个SELECT语句,数据集会自动返回出来,而在Oracle中,需要通过一个指针来实现数据集的返回。来看具体的例子。
首先,我们来建立一个包,包头部分如下,它相当于C++中的头文件,用作声明之用,没有任何实现用的代码。

CREATE OR REPLACE PACKAGE TEST.PKG_TEST IS
    TYPE MYCURSOR IS REF CURSOR;
    PROCEDURE GET_DEC_BILL_LIST(cur_OUT OUT MYCURSOR);
END;

以上代码中,第一步,通过TYPE建立了一个指针类型MYCURSOR。第二步,声明了:此包中有一个存储过程GET_DEC_BILL_LIST,并且,这个存储过程中有一个cur_OUT的输出变量,其类型为MYCURSOR。
然后,我们来建立一个包体:

CREATE OR REPLACE PACKAGE BODY TEST.PKG_TEST IS
       PROCEDURE GET_DEC_BILL_LIST(cur_OUT OUT MYCURSOR) AS
       BEGIN
            OPEN cur_OUT FOR SELECT * FROM ALL_TABLES WHERE OWNER='SYS';
       END;
END;

以上代码中,实现了GET_DEC_BILL_LIST,其实质是打开了一个指针,其内容为SYS用户下的所有表的情况。这样子,数据库部分就Ready了。
接下来,我们就可以通过DAAB来调用这个存储过程了:

using Microsoft.Practices.EnterpriseLibrary.Data;
//Other Code here
//

        private void button1_Click(object sender, EventArgs e)
        {
            Database db = DatabaseFactory.CreateDatabase("LocalOracle"); //建立数据库对象
            //全称:TEST用户下PKG_TEST包中的GET_DEC_BILL_LIST存储过程
            string spName = "TEST.PKG_TEST.GET_DEC_BILL_LIST";
            try
            {
                DbCommand cmd = db.GetStoredProcCommand(spName); //获取Command对象
                DataSet ds;
                ds = db.ExecuteDataSet(cmd); //执行SQL语句
                dataGridView1.DataSource = ds.Tables[0].DefaultView;//绑定数据并且显示
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            
        }

执行效果如图。

继续往下看,精彩继续 ^_^
如果您照着示例做,但是运行时,收到一个错误提示,说参数类型不匹配,那么,答案在这里,这是DAAB中OracleDatabase.cs中的代码:

                /// <devdoc>
        /// This is a private method that will build the Oracle package name if your stored procedure
        /// has proper prefix and postfix. 
        /// This functionality is include for
        /// the portability of the architecture between SQL and Oracle datbase.
        /// This method also adds the reference cursor to the command writer if not already added. This
        /// is required for Oracle .NET managed data provider.
        /// </devdoc>        
        private void PrepareCWRefCursor(DbCommand command)
        {
            if (command == null) throw new ArgumentNullException("command");

            if (CommandType.StoredProcedure == command.CommandType)
            {
                // Check for ref. cursor in the command writer, if it does not exist, add a know reference cursor out
                // of "cur_OUT"
                if (QueryProcedureNeedsCursorParameter(command))
                {
                    AddParameter(command as OracleCommand, RefCursorName, OracleType.Cursor, 0, ParameterDirection.Output, true, 0, 0, String.Empty, DataRowVersion.Default, Convert.DBNull);
                }
            }
        }

AddParameter的第二个参数在前面的代码中有定义,为一个字符串常量:cur_OUT。所以,请修改您的存储过程,把输出指针的名称改为“cur_OUT”。
回头再看看前面示例中的C#代码,注意spName这个变量,用惯SQL Server的人一定会觉得这个名字怪怪的。能不能把代码改得像SQL Server中一样,只传递一个存储过程名称呢?呵呵,Microsoft在设计DAAB时已经考虑到了这个问题了,为了实现代码的可移植性,需要对app.config进行一下配置。在解决方案浏览器中右击app.config文本,选择Edit Enterprise Libraray Configuration。在配置好的Oracle Packages节点上右击,点击New、Oracle Package。如下图。

然后,设置新建的Oracle包属性如下图:

只要存储过程前缀与设置的相同,DAAB执行存储过程时,便会自动添加前缀,于是示例代码便可以修改如下。

private void button1_Click(object sender, EventArgs e)
        {
            Database db = DatabaseFactory.CreateDatabase("LocalOracle"); //建立数据库对象
            //string spName = "TEST.PKG_TEST.GET_DEC_BILL_LIST";//全称
            string spName="GET_DEC_BILL_LIST";//与SQL SERVER中一样,仅仅传入存储过程名称
            try
            {
                DbCommand cmd = db.GetStoredProcCommand(spName); //获取Command对象
                DataSet ds;
                ds = db.ExecuteDataSet(cmd); //执行SQL语句
                dataGridView1.DataSource = ds.Tables[0].DefaultView;//绑定数据并且显示
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }

        }

总结一下,通过DAAB,我们实现了在C#中,调用ORACLE的存储过程返回一个数据集,并且,通过简单的配置,把调用方法与SQL统一了起来。
=================
oracle存储过程如何返回数据集?
=====
oracle 只能用cursor返回结果集呀! 
或者可以用基于session的临时表然后你在程序中从表中获取数据
=====
1.定义一个输出变量  
rcResult out PK_Var.RC   
2.打开这个记录集   
OPEN rcResult FOR sSQL;

CREATE OR REPLACE PACKAGE pkg_test 
AS   
  TYPE myrctype IS REF CURSOR;   
  PROCEDURE get (p_id NUMBER, p_rc OUT myrctype);   
END pkg_test;   
/   
-------------------    
CREATE OR REPLACE PACKAGE BODY pkg_test   
AS   
 PROCEDURE get(p_id NUMBER, p_rc OUT myrctype)   
  IS   
    sqlstr VARCHAR2 (500);   
BEGIN   
  IF p_id = 0 THEN   
    OPEN p_rc FOR   
     SELECT ID, NAME, sex, address, postcode, birthday FROM student;   
  ELSE sqlstr := 'selectid,name,sex,address,postcode,birthday from student where id=:w_id';   
  OPEN p_rc FOR sqlstr USING p_id;   
  END IF;   
 END get;   
END pkg_test;

=========
过程可以返回结果集合,关键是是使用引用游标   
测试表:table_test   
--建立包   
  create   or   replace   package   pkg_test   as   
          --定义一个返回类型为表table_test的记录结构的引用游标类型rc_test   
          type rc_test is ref cursor return table_test%rowtype;   
          --声明过程,参数是类型为rc_test的引用游标cur,传出参数   
          procedure get_data(cur out rc_test);   
  end   pkg_test;   
--定义包体   
create or replace package body pkg_test as   
  procedure get_data(cur out rc_test) is   
     begin   
       open cur for select * from table_test;   
  end get_data;   
end pkg_test;
=============

123 c#调用oracle存储过程返回数据集 --通过oracle存储过程返回数据集的更多相关文章

  1. java servlet调用带有多个返回结果集的存储过程

    一.mysql存储过程 这里我先说下我这个功能实现的逻辑及途中遇到的一些问题.这个存储过程一共带两个输入参数,一共关联到两张表的查询,每个参数都对应查询表中的一个判断,所以一共返回了两个结果集(当然要 ...

  2. PB中用oracle的存储过程返回记录集做数据源来生成数据窗口,PB会找不到此存储过程及不能正常识别存储过程的参数问题(转)

    (转)在PB中用oracle的存储过程返回记录集做数据源来生成数据窗口 首先oracle的存储过程写法与MSSQL不一样,差别比较大. 如果是返回数据集的存储过程则需要利用oracle的包来定义游标. ...

  3. oracle学习-存储过程返回一个值,和返回一个结果集

    一.返回一个值 --创建存储过程 create or replace procedure sp_hu_test(spcode in varchar2,spname out varchar2)is be ...

  4. C# 调用存储过程操作 OUTPUT参数和Return返回值

    本文转载:http://www.cnblogs.com/libingql/archive/2010/05/02/1726104.html 存储过程是存放在数据库服务器上的预先编译好的sql语句.使用存 ...

  5. Entity Framework 调用返回标量值的存储过程

    最近项目用到EF,虽然说EF与Linq To SQL有很多地方相似,但是EF(这里指3.5版,4.0版的还没去留意)确实有些地方做得不够方便. 就拿存储过程来说吧,EF里面想调用存储过程不是直接在数据 ...

  6. sqlserver存储过程里传字段、传字符串,并返回DataTable、字符串,存储过程调用存储过程。

    经常需要查一些信息,  想写视图来返回数据以提高效率,但是用试视图不能传参,只好想到改存储过程.记录一下语法,方便以后做项目时候想不起来了用. 1:传字段返回datatable 2: 传字段回一串字符 ...

  7. MySQL存储过程中的3种循环,存储过程的基本语法,ORACLE与MYSQL的存储过程/函数的使用区别,退出存储过程方法

    在MySQL存储过程的语句中有三个标准的循环方式:WHILE循环,LOOP循环以及REPEAT循环.还有一种非标准的循环方式:GOTO,不过这种循环方式最好别用,很容易引起程序的混乱,在这里就不错具体 ...

  8. Oracle学习(12):存储过程,函数和触发器

    存储过程和存储函数 l存储在数据库中供全部用户程序调用的子程序叫存储过程.存储函数. 注意:存储过程与存储函数声明变量时,用的是as   而不是declare 存储过程与存储函数差别 存储过程不带有返 ...

  9. oracle 存储过程详细介绍(创建,删除存储过程,参数传递等)

    这篇文章主要介绍了oracle 创建,删除存储过程,参数传递,创建,删除存储函数,存储过程和函数的查看,包,系统包等相关资料,需要的朋友可以参考下   oracle 创建,删除存储过程,参数传递,创建 ...

随机推荐

  1. linux系统查看网络连接情况

    netstat命令状态说明: CLOSED                      没有使用这个套接字[netstat 无法显示closed状态] LISTEN 套接字正在监听连接[调用listen ...

  2. [Python3网络爬虫开发实战] 4.1-使用XPath

    XPath,全称XML Path Language,即XML路径语言,它是一门在XML文档中查找信息的语言.它最初是用来搜寻XML文档的,但是它同样适用于HTML文档的搜索. 所以在做爬虫时,我们完全 ...

  3. 集训第六周 数学概念与方法 概率 F题

    Submit Status Description Sometimes some mathematical results are hard to believe. One of the common ...

  4. The Bells are Ringing(枚举)

    Description Perhaps you all have heard the mythical story about Tower of Hanoi (The details of this ...

  5. Linux基础命令回顾

    前言 说到linux基础命令,网上一搜一箩筐,想学也有很多教程,如果你不幸看到此篇文章,想看就认真看完,毕竟你点进来了不是嘛? 我每次写的文章都是为了分享自己的学习成果或重要知识点,希望能帮助更多的人 ...

  6. git clone问题

    中秋节回来上班 竟然忘记带电脑了  ̄□ ̄||还好同事有备用电脑,这要是回去拿估计上午都不用干什么了,用同事电脑当然需要安装环境,下面说一下git上遇到的问题吧 (1)首先我尝试用https方式克隆代码 ...

  7. 图解使用IDEA创建第一个Java程序HelloWorld

    前几次给大家分享了怎么在自己的电脑上配置 java 环境,准备工作做好了,我们就要开始我们真正的编码学习了.下面介绍使用 IDEA 创建我们的第一个 HelloWorld 程序. 1.打开 IDEA, ...

  8. 九度oj 题目1068:球的半径和体积

    题目1068:球的半径和体积 时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:6148 解决:2269 题目描述: 输入球的中心点和球上某一点的坐标,计算球的半径和体积 输入: 球的中心点和 ...

  9. python之模块随笔记-os

    操作系统模块:import os os.remove() 删除文件 os.unlink() 删除链接文件 os.rename() 重命名文件 os.listdir() 列出指定目录下所有文件 os.c ...

  10. vue生成包报错error from UglifyJs

    mangle: { keep_fnames: true},