DB开发之oracle存储过程

1. 存储过程格式

/* Formatted on 2011/1/17 13:20:44 (QP5 v5.115.810.9015) */

CREATE OR REPLACE procedure proc_trade(

v_tradeid in number,                        --交易id

v_third_ip in varchar2,                     --第三方ip

v_third_time in date ,                      --第三方完成时间

v_thire_state in number ,                   --第三方状态

o_result out number,                       --返回值

o_detail out varchar2                     --详细描述

)

as

-- 定义变量

v_error varchar2(500);

begin

--对变量赋值

o_result:=0;

o_detail:=‘验证失败‘;

--业务逻辑处理

if v_tradeid >100 then

insert into table_name(...) values(...);

commit;

elsif v_tradeid < 100 and v_tradeid>50 then

insert into table_name(...) values(...);

commit;

else

goto log;

end if;

--跳转标志符,名称自己指定

<<log>>

o_result:=1;

--捕获异常

exception

when no_data_found

then

result := 2;

when dup_val_on_index

then

result := 3;

when others

then

result := -1;

end proc_trade;

在上面这个存储过程中使用了输入参数,并返回输出参数,这里的参数类型是我们自己指定的。 这种写法可行,但是最好使用%type 来获取参数的类型(table_name.column_name%TYPE)。 这样就不会出现参数类型的错误。

如:

CREATE OR REPLACE PROCEDURE spdispsms (

aempid      IN       otherinfo.empid%TYPE,

amsg        IN       otherinfo.msg%TYPE,

abillno     IN       otherinfo.billno%TYPE,

ainfotype   IN       otherinfo.infotype%TYPE,

aopid       IN       otherinfo.OPERATOR%TYPE,

ainfoid     OUT      otherinfo.infoid%TYPE,

RESULT      OUT      INTEGER

)

2. 存储过程中的循环

存储过程写的是业务逻辑,循环是常用的处理方法之一。

2.1  for ... in ... loop 循环

2.1.1:循环遍历游标

示例1:

CREATE OR REPLACE PROCEDURE proc_test

AS

CURSOR c1

IS

SELECT   * FROM dat_trade;

BEGIN

FOR x IN c1

LOOP

DBMS_OUTPUT.put_line (x.id);

END LOOP;

END proc_test;

示例2:

CREATE OR REPLACE PROCEDURE proc_test

AS

BEGIN

FOR x IN (SELECT   power_id FROM sys_power)

LOOP

DBMS_OUTPUT.put_line (x.power_id);

END LOOP;

END proc_test;

2.1. 2:根据数值进行循环

示例1:

CREATE OR REPLACE PROCEDURE proc_test (v_num IN NUMBER)

AS

BEGIN

for x in 1..100 loop

dbms_output.put_line(x);

end loop;

END proc_test;

示例2:在过程里指定输入参数v_num. 在调用过程时指定循环次数。

CREATE OR REPLACE PROCEDURE proc_test (v_num IN NUMBER)

AS

BEGIN

FOR x IN 1 .. v_num

LOOP

DBMS_OUTPUT.put_line (x);

END LOOP;

END proc_test;

2.2  loop 循环

LOOP

DELETE FROM orders

WHERE senddate < TO_CHAR (ADD_MONTHS (SYSDATE, -3),

‘yyyy-mm-dd‘)

AND ROWNUM < 1000;

EXIT WHEN SQL%ROWCOUNT < 1;

COMMIT;

END LOOP;

这里的SQL%ROWCOUNT 是隐士游标。 除了这个,还有其他几个:%found,%notfound, %isopen。

2.3  while 循环

CREATE OR REPLACE PROCEDURE proc_test (v_num IN NUMBER)

AS

i   NUMBER := 1;

BEGIN

WHILE i < v_num

LOOP

BEGIN

i := i + 1;

DBMS_OUTPUT.put_line (i);

END;

END LOOP;

END proc_test;

3. 存储过程中的判断

判断也是存储过程中最常用的方法之一。

3.1  if ... elsif ... else ... 判断

CREATE OR REPLACE PROCEDURE proc_test (v_num IN NUMBER)

AS

BEGIN

IF v_num < 10

THEN

DBMS_OUTPUT.put_line (v_num);

ELSIF v_num > 10 AND v_num < 50

THEN

DBMS_OUTPUT.put_line (v_num - 10);

ELSE

DBMS_OUTPUT.put_line (v_num - 50);

END IF;

END proc_test;

3.2  case ... when ... end case 判断

CREATE OR REPLACE PROCEDURE proc_test (v_num IN NUMBER)

AS

BEGIN

case v_num

when 1 then

DBMS_OUTPUT.put_line (v_num);

when 2 then

DBMS_OUTPUT.put_line (v_num);

when 3 then

DBMS_OUTPUT.put_line (v_num);

else null;

end case;

END proc_test;

4. 游标

存储过程中使用游标也是很常见的。 这里的游标分两种:

4.1  Cursor型游标(不能用于参数传递)

这种方法具体参考 2.1.1:循环遍历游标 中的示例。

4.2  SYS_REFCURSOR型游标

该游标是Oracle以预先定义的游标,可作出参数进行传递。

注意一点:SYS_REFCURSOR只能通过OPEN方法来打开和赋值

4.2.1  我们可以使用这种类似的游标来返回一个结果集:

CREATE OR REPLACE procedure  proc_test(

checknum in number,  --每次返回的数据量

ref_cursor out sys_refcursor  --返回的结果集,游标

)

as

begin

open ref_cursor for select * from (select * from dat_trade where state=41 order by id) where rownum<checknum;

end proc_test;

/

SYS_REFCURSOR中可使用三个状态属性:

(1).            %NOTFOUND(未找到记录信息)

(2).            %FOUND(找到记录信息)

(3).            %ROWCOUNT(然后当前游标所指向的行位置)

CREATE OR REPLACE PROCEDURE proc_test (

checknum     IN     NUMBER, --每次返回的数据量

ref_cursor      OUT sys_refcursor --返回的结果集,游标

)

AS

t_tmp   table_name%ROWTYPE;

BEGIN

OPEN ref_cursor FOR

SELECT   *

FROM   (  SELECT   *

FROM   table_name

WHERE   state = 41

ORDER BY   id)

WHERE   ROWNUM < checknum;

--循环游标

LOOP

FETCH ref_cursor INTO   t_tmp;

EXIT WHEN ref_cursor%NOTFOUND;

--    DBMS_OUTPUT.put_line (t_tmp.id);

UPDATE   table_name

SET   state = 53

WHERE   id = t_tmp.id;

COMMIT;

END LOOP;

CLOSE ref_cursor;

END proc_test;

五. 存储过程的调试

如果使用PL/SQL Developer 或者TOAD 工具的话,调试还是很方便的。 如果是在Sqlplus里,我们可以使用:

SQL>show errors

来查看错误。不过在开发中估计也很少有人直接使用sqlplus来写存储过程。 效率低,调试又麻烦。 还是使用工具方便点。我一直使用的是Toad的。

如果想在某处退出存储过程,直接使用Return;就可以了。 与存储过程编写相关的数组和游标, 这两块说起来还是有很多东西。 在上面的示例中, 也简单的举了几个有关游标与存储过程编写的例子。

总之,写代码都是都是费脑子的事,相比之下还是做管理DBA舒服点,虽然压力大很多,至少不用这么费心思去整理业务逻辑。

时间: 2024-10-09 22:56:41

DB开发之oracle存储过程的相关文章

DB开发之mysql

1. MySQL 4.x版本及以上版本提供了全文检索支持,但是表的存储引擎类型必须为MyISAM,以下是建表SQL,注意其中显式设置了存储引擎类型 CREATE TABLE articles ( id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY, title VARCHAR(200), body TEXT, FULLTEXT (title,body)) ENGINE=MyISAM DEFAULT CHARSET=utf8; 其中FULLTEX

Android开发之SQLite数据库详解

Android开发之SQLite数据库详解 请尊重他人的劳动成果,转载请注明出处:Android开发之SQLite数据库详解 http://blog.csdn.net/fengyuzhengfan/article/details/40194393 Android系统集成了一个轻量级的数据库:SQLite, SQLite并不想成为像Oracle.MySQL那样的专业数据库.SQLite只是一个嵌入式的数据库引擎,专门适用于资源有限的设备上(如手机.PDA等)适量数据存取. 虽然SQLite支持绝大

Android开发之SQLite优化

本文原地址为:http://blog.csdn.net/horkychen/article/details/18892223 关于SQLite的优化,首先是能用SQL语句批次处理的,就不要单笔操作,Cursor就更是能不用就不用.比如成批的DELETE/UPDATE,将条件组装到SQL语句,会比使用CURSOR一条条的查再删效率要高很多(若干年前就曾使用存储过程代替单笔操作,将一次批量计算时间从一天缩到了数分钟以内,参考).其次是对操作的优化:对于INSERT/UPDATE操作较多时使用事务,如

Android 安全开发之 ZIP 文件目录遍历

1.ZIP文件目录遍历简介 因为ZIP压缩包文件中允许存在"../"的字符串,攻击者可以利用多个"../"在解压时改变ZIP包中某个文件的存放位置,覆盖掉应用原有的文件.如果被覆盖掉的文件是动态链接so.dex或者odex文件,轻则产生本地拒绝服务漏洞,影响应用的可用性,重则可能造成任意代码执行漏洞,危害用户的设备安全和信息安全.比如近段时间发现的"寄生兽"漏洞.海豚浏览器远程命令执行漏洞.三星默认输入法远程代码执行漏洞等都与ZIP文件目录遍历有

具体解释EBS接口开发之WIP模块接口

整体说明 文档目的 本文档针对WIP模块业务功能和接口进行分析和研究,对採用并发请求方式和调用API方式分别进行介绍 内容 WIP模块经常使用标准表简单介绍 WIP事物处理组成 WIP相关业务流程 WIP相关API研究事例 (十)參考文档(七)採购相关的一些知识 (一)WIP模块经常使用标准表简单介绍 1.1   经常使用标准表 例如以下表中列出了与WIP导入相关的表和说明: 表名 说明 其它信息 BOM_STRUCTURES_B BOM头信息 BOM_COMPONENTS_B BOM组件信息

监控开发之用munin来自定义插件监控redis和mongodb

求监控组的大哥大妹子们干点事,真不容易 ! 要问他们是谁?  他们是神 .轻易别找他们,因为找了也是白找. 上次因为python和redis长时间brpop的时候,会有线程休眠挂起的情况,所有通知报警平台被下线了.这次算是完美解决了.再把他给上线.这两公司的告警已经开始往我这边的接口开始仍了. 这边正在改zabbix cmdb的控制,所以暂时不能登录.等搞好了后,让他们搞下redis和mogodb的监控,居然还让我发邮件和提供脚本及思路啥的...   一寻思,又要去zabbix,又要写脚本,还不

基于xmpp openfire smack开发之Android客户端开发[3]

在上两篇文章中,我们依次介绍openfire部署以及smack常用API的使用,这一节中我们着力介绍如何基于asmack开发一个Android的客户端,本篇的重点在实践,讲解和原理环节,大家可以参考前两篇的文章 基于xmpp openfire smack开发之openfire介绍和部署[1] 基于xmpp openfire smack开发之smack类库介绍和使用[2] 1.源码结构介绍 activity包下存放一些android页面交互相关的控制程序,还有一个些公共帮助类 db包为sqlite

PDMS二次开发之PML开发一些常见查询语句

1.查找session 以及session number var !DBname DBname !db = object db(!DBname) !session = !db.lastsession() 下面是查询结果截图 q var !db q var !sessioon.number 2.从某个时间段到当前,模型的差异文件判断模型是否发生修改,并写入文件. alpha log /$!file  overwrite DIFFERENCE $!ojbName SINCE 15:36 14 May

ArcGIS Engine开发之旅02--ArcGIS Engine中的类库

原文 ArcGIS Engine开发之旅02--ArcGIS Engine中的类库 System类库 System类库是ArcGIS体系结构中最底层的类库.System类库包含给构成ArcGIS的其他类库提供服务的组件.System类库中定义了大量开发者可以实现的接口.AoInitializer对象就是在System类库中定义的,所有的开发者必须使用这个对象来初始化ArcGISEngine和解除ArcGIS Engine的初始化.开发者不能扩展这个类库,但可以通过实现这个类库中包含的接口来扩展A