C#连接Oracle数据库通过存储过程操作数据库 收藏 此文于2011-06-07被推荐到CSDN首页

此文于2011-06-08被推荐到CSDN首页

如何被推荐?

之前笔者一直用C#连接SQL Server数据库。近期由于工作需要,需要用C#连接Oracle数据库,并且要通过存储过程,来操作数据库中的数据,实现增、删、改、查(有分页功能)功能。并且,为了今后对数据库扩展方便,对现在的代码改动最小的情况下,实现数据库的平稳切换,必须采用OleDB的方式连接Oracle数据库、操作存储过程。

首先去网上搜索资料,确实找到了很多C#连接Oracle数据库,和用存储过程操作数据库的资料。但是仔细研究发现,清一色的全部是使用OracleClient(Oracle专用驱动)的方式对Oracle数据库及存储过程进行操作。没办法,只能自己动手、丰衣足食。经过3天左右的辛苦努力,终于实现了用OleDB连接Oracle数据库,并且用存储过程来操作Oracle数据库的方法。下面将实现方式总结一下。

用OleDB操作Oracle存储过程,有几个难题;

1、  返回记录集,也就是Oracle的游标;

2、  对于某些特殊的应用,有可能需要返回多个记录集;

3、  将存储过程中的数据,通过输出参数的形式返回给程序(因为要做分页,需要将记录数输出来);

4、  对Text大文本字段(对应Oracle的数据类型是CLOB)的增、改、查操作;

5、  对特殊字符的查询,如查询文本中是否包含“%”、“\”、“’”、“_”等符号;

接下来,主要针对以上问题,进行介绍;

一、连接Oracle数据库

连接Oracle数据库,主要有2种方式。一种是使用微软的数据库驱动进行连接;另外一种是使用Oracle的数据库驱动进行连接;

经过在网上查资料,说是Oracle的数据库驱动,中文可能会出现乱码;微软的驱动虽然中文没有乱码,但是对于CLOB类型的字段,无法操作;经过对比,决定使用Oracle的数据库驱动。因为应用中,肯定要有CLOB类型的字段操作;但是经过测试,未发现中文出现乱码的情况;

Ø         Oracle数据库连接方式:

Provider=OraOLEDB.Oracle.1;User ID=username;password=dbpassword;Data Source=databasename;Persist Security Info=True;Extended Properties='PLSQLRSet=1';

Extended Properties='PLSQLRSet=1'

注意:上面这个属性一定要带上,否则无法操作有返回游标参数的存储过程;

Ø         微软的数据库连接方式:

Provider=MSDAORA.1;Data Source=allrun;User ID=allrunadmin;Password=allrun;Persist Security Info=True;

建议使用Oracle数据库的连接方式。

二、存储过程,返回多个记录集

Oracle存储过程脚本:

view plaincopy to clipboardprint?

--包

create or replace

PACKAGE               "DESKTOP_PAGE_PACKAGE" as

TYPE T_CURSOR IS REF CURSOR;

procedure GetDesktopPage (RecordTotal OUT NUMBER, curRecordTotal OUT T_CURSOR, curDesktopPage OUT T_CURSOR);

end;

--包体

create or replace

PACKAGE BODY               "DESKTOP_PAGE_PACKAGE" as

procedure GetDesktopPage (RecordTotal OUT NUMBER, curRecordTotal OUT T_CURSOR, curDesktopPage OUT T_CURSOR) is

begin

--记录集1

OPEN curRecordTotal FOR

SELECT 1679 FROM DUAL;

--记录集2

OPEN curDesktopPage FOR

SELECT * FROM DESKTOP_PAGE;

--输出参数

RecordTotal := 1688;

end;

end;

--包

create or replace

PACKAGE               "DESKTOP_PAGE_PACKAGE" as

TYPE T_CURSOR IS REF CURSOR;

procedure GetDesktopPage (RecordTotal OUT NUMBER, curRecordTotal OUT T_CURSOR, curDesktopPage OUT T_CURSOR);

end;

--包体

create or replace

PACKAGE BODY               "DESKTOP_PAGE_PACKAGE" as

procedure GetDesktopPage (RecordTotal OUT NUMBER, curRecordTotal OUT T_CURSOR, curDesktopPage OUT T_CURSOR) is

begin

--记录集1

OPEN curRecordTotal FOR

SELECT 1679 FROM DUAL;

--记录集2

OPEN curDesktopPage FOR

SELECT * FROM DESKTOP_PAGE;

--输出参数

RecordTotal := 1688;

end;

end;

C#程序操作存储过程:

view plaincopy to clipboardprint?

OleDbCommand store = new OleDbCommand ();

store.Parameters.Clear ();

store.Connection = con;

store.CommandType = CommandType.StoredProcedure;

store.CommandText = "DESKTOP_PAGE_PACKAGE.GetDesktopPage";

store.Parameters.Add ("RecordTotal", OleDbType.Numeric).Value = null;

store.Parameters["RecordTotal"].Size = -1;

store.Parameters["RecordTotal"].Scale = 0;

store.Parameters["RecordTotal"].Precision = 0;

store.Parameters["RecordTotal"].Direction = ParameterDirection.Output;

try

{

OleDbDataAdapter da = new OleDbDataAdapter (store);

DataSet ds = new DataSet ();

da.Fill (ds);

Response.Write ("输出参数返回记录数:" + store.Parameters["RecordTotal"].Value + "
");

for (int i = 0; i < ds.Tables[0].Rows.Count; i++)

{

Response.Write ("记录集1返回记录数:" + ds.Tables[0].Rows[i][0] + "
");

}

Response.Write ("
记录集2返回数据:
");

for (int i = 0; i < ds.Tables[1].Rows.Count; i++)

{

Response.Write (ds.Tables[1].Rows[i][0] + ", " + ds.Tables[1].Rows[i][1] + ", " + ds.Tables[1].Rows[i][2] + "
");

}

}

finally

{

con.Close ();

}

OleDbCommand store = new OleDbCommand ();

store.Parameters.Clear ();

store.Connection = con;

store.CommandType = CommandType.StoredProcedure;

store.CommandText = "DESKTOP_PAGE_PACKAGE.GetDesktopPage";

store.Parameters.Add ("RecordTotal", OleDbType.Numeric).Value = null;

store.Parameters["RecordTotal"].Size = -1;

store.Parameters["RecordTotal"].Scale = 0;

store.Parameters["RecordTotal"].Precision = 0;

store.Parameters["RecordTotal"].Direction = ParameterDirection.Output;

try

{

OleDbDataAdapter da = new OleDbDataAdapter (store);

DataSet ds = new DataSet ();

da.Fill (ds);

Response.Write ("输出参数返回记录数:" + store.Parameters["RecordTotal"].Value + "
");

for (int i = 0; i < ds.Tables[0].Rows.Count; i++)

{

Response.Write ("记录集1返回记录数:" + ds.Tables[0].Rows[i][0] + "
");

}

Response.Write ("
记录集2返回数据:
");

for (int i = 0; i < ds.Tables[1].Rows.Count; i++)

{

Response.Write (ds.Tables[1].Rows[i][0] + ", " + ds.Tables[1].Rows[i][1] + ", " + ds.Tables[1].Rows[i][2] + "
");

}

}

finally

{

con.Close ();

}

因为主要是介绍操作数据库存储过程的方法,如何连接数据库请自己写;

一、对CLOB字段的增、改、查;

假设表名为:DESKTOP_PAGE,包含2个字段:USERCODE(普通字符串)、CONTENT(CLOB类型)

Oracle存储过程脚本为:

view plaincopy to clipboardprint?

--包

create or replace

PACKAGE DESKTOP_TEXTLIST_PACKAGE AS

TYPE T_CURSOR IS REF CURSOR;

--CrudAction:0:增;1:读;2:改;3:删;

--IOFields:查、改的字段列表字符串,使用分号分隔

--OrderBys:排序字段

--PageNo:页码

--PageSize:每页记录数

--RecordTotal:总记录数

--RecordSet:返回记录集

procedure DesktopTextListStorer (CrudAction IN INTEGER, fldUserCode IN NVARCHAR2, fldContent IN NCLOB, IOFields IN NVARCHAR2, OrderBys IN NVARCHAR2, PageNo IN  INTEGER, PageSize IN INTEGER, RecordTotal OUT NUMBER, RecordSet IN OUT T_CURSOR);

END DESKTOP_TEXTLIST_PACKAGE;

--包体:

create or replace

PACKAGE BODY DESKTOP_TEXTLIST_PACKAGE AS

strFields VARCHAR2 (4000);

strOrderBys VARCHAR2 (4000);

strJoin VARCHAR2 (10);

strCond VARCHAR2 (4000);

strLike VARCHAR2 (500);

strWhere VARCHAR2 (10);

strAnd VARCHAR2 (10);

strSQLCalc VARCHAR2 (4000);

strSQLView VARCHAR2 (4000);

strEscape VARCHAR2 (500);

--CrudAction:0:增;1:读;2:改;3:删;

procedure DesktopTextListStorer (CrudAction IN INTEGER, fldUserCode IN NVARCHAR2, fldContent IN NCLOB, IOFields IN NVARCHAR2, OrderBys IN NVARCHAR2, PageNo IN  INTEGER, PageSize IN INTEGER, RecordTotal OUT NUMBER, RecordSet IN OUT T_CURSOR) AS

BEGIN

RecordTotal := 0;

IF CrudAction < 0 OR CrudAction > 3 OR CrudAction IS NULL THEN

RETURN;

END IF;

IF CrudAction = 0 THEN

INSERT INTO DESKTOP_TEXTLIST ("USERCODE", "CONTENT")

VALUES (fldUserCode, fldContent);

RETURN;

END IF;

IF CrudAction = 2 then

IF IOFields IS NULL THEN

UPDATE DESKTOP_TEXTLIST

SET "CONTENT" = FLDCONTENT,

"FUNCODE" = FLDFUNCODE

WHERE "USERCODE" = fldUserCode;

ELSE

strCond := ',' + IOFields + ',';

strCond := REPLACE (strCond, ',USERCODE,', ',USERCODE=' || fldUserCode || ',');

strSQLView := 'UPDATE DESKTOP_PAGE'

|| ' SET ' || strCond

|| ' WHERE USERCODE=''' || fldUserCode || ''';

EXECUTE IMMEDIATE strSQLView;

IF INSTR (IOFIELDS, ',CONTENT,') > 0 THEN

UPDATE DESKTOP_TEXTLIST

SET "CONTENT" = fldContent

WHERE "USERCODE" = FLDUSERCODE;

END IF;

END IF;

RETURN;

END IF;

strCond := NULL;

strJoin := NULL;

strEscape := 'ESCAPE CHR (92 USING NCHAR_CS)';

IF fldUserCode IS NOT NULL THEN

strCond := strCond || strJoin || ' USERCODE = ''' || REPLACE (fldUserCode, '''', '''''') || '''';

strJoin := ' AND';

END IF;

IF FLDCONTENT IS NOT NULL THEN

strLike := REPLACE (fldContent, '''', '''''');

strCond := strCond || strJoin || ' DBMS_LOB.INSTR (CONTENT, ''' || strLike || ''') > 0';

strJoin := ' AND';

END IF;

IF strCond IS NULL THEN

strWhere := '';

strAnd := '';

ELSE

strWhere := ' WHERE';

strAnd := ' AND';

END IF;

IF CrudAction = 1 THEN

IF IOFields IS NULL THEN

strFields := 'DESKTOP_TEXTLIST.*';

ELSE

strFields := IOFields;

END IF;

IF OrderBys IS NULL THEN

strOrderBys := 'USERCODE, PAGECODE, FUNCODE';

ELSE

strOrderBys := REPLACE (OrderBys, ':0', '');

strOrderBys := REPLACE (strOrderBys, ':1', ' DESC');

END IF;

strSQLCalc := 'SELECT COUNT(*)'

|| ' FROM DESKTOP_TEXTLIST'

|| STRWHERE || STRCOND;

EXECUTE IMMEDIATE  strSQLCalc INTO RecordTotal;

IF PageNo IS NULL THEN

strSQLView := 'SELECT ' || strFields

|| ' FROM DESKTOP_TEXTLIST'

|| strWhere || strCond

|| ' ORDER BY ' || strOrderBys;

ELSE

strSQLView := 'SELECT * FROM ('

|| ' SELECT ' || strFields || ', rownum rn FROM  DESKTOP_TEXTLIST'

|| ' WHERE rownum <= ' || (PageSize * PageNo)

|| ' ORDER BY ' || strOrderBys || ')'

|| ' WHERE rn >= ' || (PageSize * (PageNo  -1))

|| strAnd || strCond

|| ' ORDER BY ' || strOrderBys;

END IF;

OPEN RecordSet FOR strSQLView;

return;

ELSE

strSQLView := 'DELETE DESKTOP_TEXTLIST'

|| strWhere || strCond;

EXECUTE IMMEDIATE strSQLView;

END IF;

END DesktopTextListStorer;

END DESKTOP_TEXTLIST_PACKAGE;

--包

create or replace

PACKAGE DESKTOP_TEXTLIST_PACKAGE AS

TYPE T_CURSOR IS REF CURSOR;

--CrudAction:0:增;1:读;2:改;3:删;

--IOFields:查、改的字段列表字符串,使用分号分隔

--OrderBys:排序字段

--PageNo:页码

--PageSize:每页记录数

--RecordTotal:总记录数

--RecordSet:返回记录集

procedure DesktopTextListStorer (CrudAction IN INTEGER, fldUserCode IN NVARCHAR2, fldContent IN NCLOB, IOFields IN NVARCHAR2, OrderBys IN NVARCHAR2, PageNo IN  INTEGER, PageSize IN INTEGER, RecordTotal OUT NUMBER, RecordSet IN OUT T_CURSOR);

END DESKTOP_TEXTLIST_PACKAGE;

--包体:

create or replace

PACKAGE BODY DESKTOP_TEXTLIST_PACKAGE AS

strFields VARCHAR2 (4000);

strOrderBys VARCHAR2 (4000);

strJoin VARCHAR2 (10);

strCond VARCHAR2 (4000);

strLike VARCHAR2 (500);

strWhere VARCHAR2 (10);

strAnd VARCHAR2 (10);

strSQLCalc VARCHAR2 (4000);

strSQLView VARCHAR2 (4000);

strEscape VARCHAR2 (500);

--CrudAction:0:增;1:读;2:改;3:删;

procedure DesktopTextListStorer (CrudAction IN INTEGER, fldUserCode IN NVARCHAR2, fldContent IN NCLOB, IOFields IN NVARCHAR2, OrderBys IN NVARCHAR2, PageNo IN  INTEGER, PageSize IN INTEGER, RecordTotal OUT NUMBER, RecordSet IN OUT T_CURSOR) AS

BEGIN

RecordTotal := 0;

IF CrudAction < 0 OR CrudAction > 3 OR CrudAction IS NULL THEN

RETURN;

END IF;

IF CrudAction = 0 THEN

INSERT INTO DESKTOP_TEXTLIST ("USERCODE", "CONTENT")

VALUES (fldUserCode, fldContent);

RETURN;

END IF;

IF CrudAction = 2 then

IF IOFields IS NULL THEN

UPDATE DESKTOP_TEXTLIST

SET "CONTENT" = FLDCONTENT,

"FUNCODE" = FLDFUNCODE

WHERE "USERCODE" = fldUserCode;

ELSE

strCond := ',' + IOFields + ',';

strCond := REPLACE (strCond, ',USERCODE,', ',USERCODE=' || fldUserCode || ',');

strSQLView := 'UPDATE DESKTOP_PAGE'

|| ' SET ' || strCond

|| ' WHERE USERCODE=''' || fldUserCode || ''';

EXECUTE IMMEDIATE strSQLView;

IF INSTR (IOFIELDS, ',CONTENT,') > 0 THEN

UPDATE DESKTOP_TEXTLIST

SET "CONTENT" = fldContent

WHERE "USERCODE" = FLDUSERCODE;

END IF;

END IF;

RETURN;

END IF;

strCond := NULL;

strJoin := NULL;

strEscape := 'ESCAPE CHR (92 USING NCHAR_CS)';

IF fldUserCode IS NOT NULL THEN

strCond := strCond || strJoin || ' USERCODE = ''' || REPLACE (fldUserCode, '''', '''''') || '''';

strJoin := ' AND';

END IF;

IF FLDCONTENT IS NOT NULL THEN

strLike := REPLACE (fldContent, '''', '''''');

strCond := strCond || strJoin || ' DBMS_LOB.INSTR (CONTENT, ''' || strLike || ''') > 0';

strJoin := ' AND';

END IF;

IF strCond IS NULL THEN

strWhere := '';

strAnd := '';

ELSE

strWhere := ' WHERE';

strAnd := ' AND';

END IF;

IF CrudAction = 1 THEN

IF IOFields IS NULL THEN

strFields := 'DESKTOP_TEXTLIST.*';

ELSE

strFields := IOFields;

END IF;

IF OrderBys IS NULL THEN

strOrderBys := 'USERCODE, PAGECODE, FUNCODE';

ELSE

strOrderBys := REPLACE (OrderBys, ':0', '');

strOrderBys := REPLACE (strOrderBys, ':1', ' DESC');

END IF;

strSQLCalc := 'SELECT COUNT(*)'

|| ' FROM DESKTOP_TEXTLIST'

|| STRWHERE || STRCOND;

EXECUTE IMMEDIATE  strSQLCalc INTO RecordTotal;

IF PageNo IS NULL THEN

strSQLView := 'SELECT ' || strFields

|| ' FROM DESKTOP_TEXTLIST'

|| strWhere || strCond

|| ' ORDER BY ' || strOrderBys;

ELSE

strSQLView := 'SELECT * FROM ('

|| ' SELECT ' || strFields || ', rownum rn FROM  DESKTOP_TEXTLIST'

|| ' WHERE rownum <= ' || (PageSize * PageNo)

|| ' ORDER BY ' || strOrderBys || ')'

|| ' WHERE rn >= ' || (PageSize * (PageNo  -1))

|| strAnd || strCond

|| ' ORDER BY ' || strOrderBys;

END IF;

OPEN RecordSet FOR strSQLView;

return;

ELSE

strSQLView := 'DELETE DESKTOP_TEXTLIST'

|| strWhere || strCond;

EXECUTE IMMEDIATE strSQLView;

END IF;

END DesktopTextListStorer;

END DESKTOP_TEXTLIST_PACKAGE;

四、对特殊字符的查询,如查询文本中是否包含“%”、“\”、“’”、“_”等符号;

Oracle脚本:

view plaincopy to clipboardprint?

strEscape := 'ESCAPE CHR (92 USING NCHAR_CS)';

strLike := REPLACE (fldPageName, '%', '\%');

STRLIKE := REPLACE (STRLIKE, '_', '\_');

strLike := REPLACE (strLike, '\', '\\');

strLike := REPLACE (strLike, '''', '''''');

strCond := strCond || strJoin || ' PAGENAME LIKE ''%' || strLike || '%'' ' || strEscape;

strEscape := 'ESCAPE CHR (92 USING NCHAR_CS)';

strLike := REPLACE (fldPageName, '%', '\%');

STRLIKE := REPLACE (STRLIKE, '_', '\_');

strLike := REPLACE (strLike, '\', '\\');

strLike := REPLACE (strLike, '''', '''''');

strCond := strCond || strJoin || ' PAGENAME LIKE ''%' || strLike || '%'' ' || strEscape;

以上是笔者操作Oracle数据库总结出来的一些经验,然后对大家有所帮助。s

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/cuizm/archive/2011/06/07/6528869.aspx

oracle表的历史数据转储过程,C#连接Oracle数据库通过存储过程操作数据库 - cuizm的专栏 - CSDN博客...相关推荐

  1. c 连接oracle数据库字符串,C#数据库连接字符串 - 水泛舟的专栏 - CSDN博客

    C#数据库连接字符串 在MSDN中,.net的数据库连接字符串都有详细的说明,我这里以代码范例的方式罗列一些,具体的每一项代表的意义可以参看MSDN. ADO.net 中数据库连接方式(微软提供) 微 ...

  2. mysql 多表关联建模_(四)多对多模式 - 数据库模型设计专栏 - CSDN博客

    连载之5 原创:胖子刘(转载请注明出处及作者,谢谢.)(四)多对多模式 多对多模式,也是比较常见的一种数据库设计模式,它所描述的两个对象不分主次.地位对等.互为一对多的关系.对于A表来说,一条记录对应 ...

  3. r如何连接oracle,R语言 R两种方式连接Oracle

    关注微信公共号:小程在线 关注CSDN博客:程志伟的博客 一.通过RODBC包连接oracle 1.首先在本机找到ODBC数据源,点击添加,按照自己的oracle,填写下面三个位置 2.填写完之后,点 ...

  4. ubuntu 安装Pangolin 过程_余辉亮的学习笔记的博客-CSDN博客_pangolin安装

    ubuntu 安装Pangolin 过程_余辉亮的学习笔记的博客-CSDN博客_pangolin安装

  5. 无人驾驶运动学模型——线性时变模型预测控制的思路推演过程_百叶书的博客-CSDN博客_线性时变模型预测控制 转

    无人驾驶运动学模型--线性时变模型预测控制的思路推演过程_百叶书的博客-CSDN博客_线性时变模型预测控制

  6. pl/sql远程连接oracle服务器问题(各种情况) .,plsql远程连接oracle服务器问题(各种情况).docx...

    plsql远程连接oracle服务器问题(各种情况).docx PLSQL远程连接oracle服务器问题(各种情况)1.病毒软件的防火墙可以关闭试试在连接.2.环境变量path里面没有加上%ORACL ...

  7. laravel框架连接Oracle,laravel5.8(十四)连接oracle数据库

    首先确定你的PHP已经支持oracle数据库的链接.PHP需要安装OCI8扩展. 确定PHP可以链接ORACLE数据库之后.我们使用composer安装laravel支持oracle链接的插件 yaj ...

  8. oracle 表的er图,用PowerDesingner把oracle中的表导成er图

    用PowerDesingner把oracle中的表导成er图 通过windows数据源管理,建立ODBC数据源. 我的是基于oracle10g. 打开Windows的控制面板 打开管理工具 打开数据源 ...

  9. navcat设置oracle表主键自增_初识 Oracle 表空间设置与管理

    本文出自头条号老王谈运维,转载请说明出处. 前言 表空间是 Oracle 特有的一种逻辑结构,是管理和组织 Oracle 数据文件一种方式,一个Oracle 数据库能够有一个或多个表空间,而一个表空间 ...

最新文章

  1. 如何发布Node模块到NPM社区
  2. Oracle开发常用函数与存储过程
  3. 程序与进程的区别,并发与并行的区别,多进程的实现原理
  4. 实在不好意思,最近写个项目,一直没时间来灌水
  5. Python取出两个文件中相同的电话号码及地址(文件类型为:txt文本)
  6. 福昕阅读器drm加密解密总结
  7. 是否要运行此应用程序_使用Delve调试Go应用程序
  8. 定时器中断实验 编写程序使定时器0或者定时器1工作在方式2,自动重装载模式,定时500ms使两位数码管从00、01、02……98、99每间隔500ms加1显示。
  9. Unity同一项目双开方法
  10. 如何在恢复模式下启动 Mac?
  11. fixed定位之后,如何让div上下垂直居中
  12. 怎樣制作线段动画_几何画板如何做动画,看完明白了
  13. Windows7不再卡五叶草,更新了bootx64.efi和bootmgfw.efi文件,支持安全启动,不用关闭安全启动和打开csm支持.
  14. 最新 2022维达纸业AI面试真题题库
  15. CMakeLists.txt范例
  16. 自定义桌面右键菜单-Win 10 版
  17. 操作系统MSXML组件版本过低,导致启动失败的原因
  18. [zz]美团点评智能支付核心交易系统的可用性实践
  19. 微信小程序消息订阅超详细流程步骤
  20. Servlet报错500的问题

热门文章

  1. button Show most popular product
  2. nodejs里fs.readFile的相对路径转绝对路径问题
  3. WordPress的nocache header生成原理
  4. 解决function id unknown issue
  5. SAP Fiori gateway OData开发重要的tcode SEGW背后的数据库表
  6. 英语采访问题之:你每天上班的动机是什么?
  7. 从Wiesloch火车站到SAP Walldorf总部的交通方式
  8. 关于SAP Fiori Smart Template开发的一些实际例子
  9. mysql主从复制深入研究_mysql主从复制原理,深入探讨
  10. 职高计算机自我鉴定800字,中专生自我鉴定800字与中专生计算机专业自我鉴定汇编...