您的位置:首页 > 数据库 > Oracle

Oracle 存储过程 使用示例

2011-01-30 08:11 381 查看
因为工作的需要,最近一直在写存储过程。
工作了
3
年,一直都是做管理,也没有正儿八经的去写过存储过程,
这次正好可以好好练习一下。

在这里说一条使用存储过程很重要的理由:
存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般
SQL
语句每执行一次就编译一次
,
所以使用存储过程可提高数据库执行速度。

Oracle
存储过程

定义



优点



函数

区别
http://blog.csdn.net/tianlesoftware/archive/2010/01/27/5261364.aspx
Oracle

查看



存储过程

触发器

函数

等对象定义语句的方法
http://blog.csdn.net/tianlesoftware/archive/2010/06/19/5679293.aspx
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
舒服点,虽然压力大很多,至少不用这么费心思去整理业务逻辑。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: