本文共 4955 字,大约阅读时间需要 16 分钟。
1.普通的存储过程
eg.
create or replace procedure proctest1
is
begin
dbms_output.put_line('my fisrt proctest1 is beginning ....');
end;
/
--执行存储过程--报无效的SQL错误
-- execute proctest1();
--调用存储过程
call proctest1();
说明:
1.在sql的执行窗口中只能调用"call proctest1();",这样执行就是把“call proctest1()”
当成一个SQL语句,而execute proctest1();不是一个SQL语句,是一个执行体,执行体调用必须
在命令窗口,把这句话当成一个整体,也就是plsql块,但是,要在sql窗口中执行也可以,这样调用:
begin
proctest1;
end;
/
2.传入带参数的存储过程
create or replace procedure proctest2(tempId in emp.empno%TYPE)
is
nameValue emp.ename%TYPE;
begin
select ename into nameValue from emp where emp.empno = tempId;
dbms_output.put_line(nameValue);
end;
/
--执行存储过程--报:ORA-00900:无效的SQL语句
execute proctest2(7934);
--调用存储过程
call proctest2(7934);
3.带返回值的存储过程
create or replace procedure proctest3(tempId in emp.empno%TYPE,tempName out emp.ename%TYPE)
is
nameValue emp.ename%TYPE;
begin
select ename into nameValue from emp where emp.empno = tempId;
tempName := nameValue;
end;
--调用存储过程
declare name1 emp.ename%TYPE;
begin
proctest3(7934,name1);
dbms_output.put_line('name: ' || name1);
end;
/
===========================================
存储过程其实就是能完成一定操作的一组SQL语句集,只不过这组语句是放在数据库中的。
第一、大大提高效率。存储过程本身的执行速度非常快,而且,调用存储过程可以大大减少同数据库的交互次数。
第二、提高安全性。假如将SQL语句混合在代码中,一旦代码失密,同时也就意味着库结构失密。
第三、有利于SQL语句的重用。
1.存储过程的最简单写法
eg1.
create or replace procedure p_test1
is
begin
null;
end;
/
--调用
call p_test1();
eg.2
create or replace procedure p_test2(
param1 varchar2,
param2 out varchar2,
param3 in out varchar2
)
as
v_name varchar2(20);
begin
v_name := 'tom';
param3 := v_name;
dbms_output.put_line('param3: ' || param3);
end;
--调用
declare name1 varchar2(20);
begin
p_test2('tom',name1,name1);
dbms_output.put_line('name: ' || name1);
end;
/
说明:
1. CREATE OR REPLACE PROCEDURE test1 是一个SQL语句通知Oracle数据库去创建一个叫做test1存储过程, 如果存在就覆盖它;
如果没有or replace语句,则仅仅是新建一个存储过程。如果系统存在该存储过程,则会报错。
Create or replace procedure 如果系统中没有此存储过程就新建一个,
如果系统中有此存储过程则把原来删除掉,重新创建一个存储过程。
2. IS关键词表明后面将跟随一个PL/SQL体。
3. BEGIN关键词表明PL/SQL体的开始。
4. NULL PL/SQL语句表明什么事都不做,这句不能删去,因为PL/SQL体中至少需要有一句;
5. END关键词表明PL/SQL体的结束
6. IN 表示输入参数,按值传递方式。
7. OUT 表示输出参数,可以理解为按引用传递方式。可以作为存储过程的输出结果,供外部调用者使用。
8. IN OUT 即可作输入参数,也可作输出参数。
9. 参数的数据类型只需要指明类型名即可,不需要指定宽度。 参数的宽度由外部调用者决定。
10. 变量声明块:紧跟着的as (is )关键字,可以理解为pl/sql的declare关键字,用于声明变量。
变量声明块用于声明该存储过程需要用到的变量,它的作用域为该存储过程。
另外这里声明的变量必须指定宽度。遵循PL/SQL的变量声明规范。
11. 过程语句块:从begin 关键字开始为过程的语句块。存储过程的具体逻辑在这里来实现。
12. 异常处理块:关键字为exception ,为处理语句产生的异常。该部分为可选
13. 结束块:由end关键字结果。
===================================================================================
1.存储过程的参数传递方式
存储过程的参数传递有三种方式:IN,OUT,IN OUT
IN按值传递,并且它不允许在存储过程中被重新赋值。如果存储过程的参数没有指定参数传递类型,默认为IN。
eg1.
create or replace procedure p_test3(
param1 varchar2,
param2 out varchar2,
param3 in out varchar2
)
as
v_name varchar2(20);
begin
param1 := 'tom';
param2 := 'jerry';
v_name := 'hanchao';
param3 := v_name;
dbms_output.put_line('param3:' || param3);
dbms_output.put_line('param2:' || param2);
end;
--编译就会报错,错误如下
PROCEDURE SCOTT.P_TEST3 编译错误
错误:PLS-00363: 表达式 'PARAM1' 不能用作赋值目标
行:9
文本:param1 := 'tom';
错误:PL/SQL: Statement ignored
行:9
文本:param1 := 'tom';
说明:这一点和其他高级语言都不同。它相当于java在参数前面加上final关键字了。
eg2.
create or replace procedure p_test4(
param1 varchar2,
param2 out varchar2,
param3 in out varchar2
)
as
v_name varchar2(20);
begin
-- param1 := 'tom';
--param2 := 'jerry';
v_name := 'hanchao';
param3 := v_name;
dbms_output.put_line('param3:' || param3);
dbms_output.put_line('param2:' || param2);
end;
--注释掉: param1 := 'tom'; 编译通过,→ 调用
declare p_name varchar2(20) := 'alax';
p_name2 varchar2(20);
begin
p_test4('tom',p_name,p_name2);
dbms_output.put_line('param2:' || p_name);
end;
说明:OUT 参数:作为输出参数,需要注意,当一个参数被指定为OUT类型时,
就算在调用存储过程之前对该参数进行了赋值,在存储过程中该参数的值仍然是null.
对于IN参数,其宽度是由外部决定。
对于OUT 和IN OUT 参数,其宽度是由存储过程内部决定。
因此,在写存储过程时,对参数的宽度进行说明是非常有必要的,最明智的方法就是参数的数据类型使用%type。这样双方就达成了一致。
→→ 具体见下面的链接。
2.参数的默认值:存储过程的参数可以设置默认值
可以通过default 关键字为存储过程的参数指定默认值。在对存储过程调用时,就可以省略默认值。
需要注意的是:默认值仅仅支持IN传输类型的参数。OUT 和 IN OUT不能指定默认值
eg1.
create or replace procedure p_test5(
p1 varchar2,
p2 varchar2 default 'xiweiyuan')
as
begin
dbms_output.put_line('p1:' || p1);
dbms_output.put_line('p2:' || p2);
end;
--调用
call p_test5('hanchao');
eg2.
create or replace procedure p_test6(
p1 varchar2 default 'xiweiyuan',
p2 varchar2)
as
begin
dbms_output.put_line('p1:' || p1);
dbms_output.put_line('p2:' || p2);
end;
-- 调用
call p_test6('hanchao');-- 会报错 → 对于默认参数不是排在组后的情况,应该这么去调用
call p_test6(p2 => 'hanchao');
3.存储过程的内部块:存储过程的结构,语句块由begin开始,以end结束。这些块是可以嵌套。在语句块中可以嵌套任何以下的块。
Declare … begin … exception … end;
create or replace procedure innerBlock(p1 varchar2)
as
v1 varchar2(10) := 'out1';
begin
dbms_output.put_line('v1:' || v1);
dbms_output.put_line('p1:' || p1);
declare inner1 varchar2(10);
begin
inner1 := 'inner1';
dbms_output.put_line('inner1:' || inner1);
declare inner2 varchar2(10);
begin
inner2 := 'inner2';
dbms_output.put_line('inner2:' || inner2);
end;
exception
when others then
null;
end;
end;
-- 调用存储过程
call innerBlock('p1');
本文转自韩立伟 51CTO博客,原文链接:http://blog.51cto.com/hanchaohan/1340691,如需转载请自行联系原作者