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');


您可以参考的地址,本文的一部分内容来自于这篇文章