1.6 存储过程

1.6.1 Procedure 定义 

1.6.1.1  定义

  存储过程(Stored Procedure  )是一组为了完成特定功能的 SQL  语句集,经编译后存储在数据库中。用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行它。存储过程是数据库中的一个重要对象,任何一个设计良好的数据库应用程序都应该用到存储过程。  存储过程是由流控制和 SQL  语句书写的过程,这个过程经编译和优化后存储在数据库服务器中,应用程序使用时只要调用即可。在ORACLE 中,若干个有联系的过程可以组合在一起构成程序包。   

 1.6.1.2  优  点

1.存储过程只在创造时进行编译,以后每次执行存储过程都不需再重新编译,而一般SQL语句每执行一次就编译一次,所以使用存储过程可提高数据库执行速度
2.当对数据库进行复杂操作时(如对多个表进行 Update、Insert、Query、Delete时),可将此复杂操作用存储过程封装起来与数据库提供的事务处理结合一起使用。   
3.存储过程可以重复使用,可减少数据库开发人员的工作量。   
4.安全性高,可设定只有某用户才具有对指定存储过程的使用权。

 

1.6.1.3  存储过程与函数的对比 

存储过程

函  数

作为 PL/SQL 语句执行

作为表达式的一部分调用

在规格说明中不包含  RETURN 子句

必须在规格说明中包含 RETURN 子句

不返回任何值

必须返回单个值

可以包含 RETURN 语句,但是与函数不同,它不能用于返回值

必须包含至少一条 RETURN
语句

1.6.2 存储过程使用示例 


1.6.2.1.  存储过程格式 

创建过程的语法:

CREATE [OR REPLACE] PROCEDURE 
   <procedure name> [(<parameter list>)]
IS|AS 
   <local variable declaration>
BEGIN
   <executable statements>
[EXCEPTION
   <exception handlers>]
END;

例如: 

CREATE OR REPLACE PROCEDURE
  find_emp(emp_no NUMBER)
AS
  empname VARCHAR2(20);
BEGIN
  SELECT ename INTO empname
  FROM EMP WHERE empno = emp_no;
  DBMS_OUTPUT.PUT_LINE('雇员姓名是 '|| empname);
EXCEPTION
  WHEN NO_DATA_FOUND THEN
    DBMS_OUTPUT.PUT_LINE ('雇员编号未找到');
END find_emp;
/

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 
)

过程参数的三种模式:
IN
    用于接受调用程序的值
    默认的参数模式
OUT
    用于向调用程序返回值 
IN OUT
    用于接受调用程序的值,并向调用程序返回更新的值

IN参数过程:

create or replace procedure proc1(i in number)
as
    a varchar2(40);
begin
    a := '';
    for j in 1..i loop
        a := a ||'*';
        dbms_output.put_line(a);
    end loop;
end;
/

dbms_output.put_line是自带的函数命令 。

在PL/SQL程序块中:  dbms_output.put_line(a);

在PL/SQL语句中: exec dbms_output.put_line('你好')

执行过程的语法

EXECUTE procedure_name(parameters_list);

SQL> exec proc1(6)

如果不显示。可能是未打开输出开关:  SQL> set serverout on

OUT参数

proc2只能在pl/sql程序段中调用

OUT参数:

ceate or replace procedure proc2(j out int)
as
begin
j := 100;
dbms_output.put_line(j);
end;
/

SQL> exec proc2(3);
BEGIN proc2(3); END;

            *
ERROR at line 1:
ORA-06550: line 1, column 13:
PLS-00363: expression '3' cannot be used as an assignment target
ORA-06550: line 1, column 7:
PL/SQL: Statement ignored

表达式3不能用作赋值目标

执行完后执行下面

declare
    k number;
begin
    proc2(k);
end;
/

IN/OUT类型存储过程:

create or replace procedure proc3(p1 in out number,p2 in out number)
is
    v_temp number;
begin
    v_temp :=p1;
    p1 := p2;
    p2 := v_temp;
end;
/


declare
    num1 number := 100;
    num2 number := 200;
begin
    proc3(num1,num2);
    dbms_output.put_line('num1=' || num1);
    dbms_output.put_line('num2=' || num2);
end;
/

将过程的执行权限授予其他用户:

SQL> GRANT EXECUTE ON find_emp TO MARTIN;

SQL> GRANT EXECUTE ON swap(存储过程名) TO PUBLIC;

删除过程:

SQL> DROP PROCEDURE find_emp;

函数:

函数是可以返回值的命名的 PL/SQL 子程序。 
创建函数的语法:
CREATE [OR REPLACE] FUNCTION 
  <function name> [(param1,param2)]
RETURN <datatype>  IS|AS 
  [local declarations]
BEGIN
  Executable Statements;
  RETURN result;
EXCEPTION
  Exception handlers;
END;

定义函数的限制:
      函数只能接受 IN 参数,而不能接受 IN OUT 或 OUT 参数
      形参不能是 PL/SQL 类型,只能是数据库类型
      函数的返回类型也必须是数据库类型


访问函数的两种方式:
     使用 PL/SQL 块
     使用 SQL 语句

创建函数

create or replace function fun_hello return varchar2
is
begin
    return 'nihao,friend';
end;
/

从 SQL 语句调用函数:
SQL> SELECT fun_hello FROM DUAL;

PL/SQL语句中调用:

declare
    ss varchar2(20);
begin
    ss := fun_hello;
    dbms_output.put_line(ss);
end;
/

create table score (student_no number(3),name varchar2(10),score number(3));
insert into score values(1,'张一', 56);
insert into score values(2,'张二', 82);
insert into score values (3,'张三', 90);
要求:创建一个函数,可以接受用户输入的学号,得到该学生的名次,并输出这个名次。

create or replace function func1(sno1 int)
return int
is
    score1 number;
    mingcil number;
begin
    select score into score1 from 分数表 where student_no=sno1;
    select count(*) into mingcil from 分数表 where score > score1;
    mingcil := mingcil +1;
    return mingcil;
end;
/

Warning: Function created with compilation errors.    警告:创建的函数带有编译错误。

演示下如何查看编译错误
SQL> show error
SQL> ed

自主事务处理
    主事务处理启动独立事务处理
    然后主事务处理被暂停
    自主事务处理子程序内的 SQL 操作
    然后终止自主事务处理
恢复主事务处理
    PRAGMA AUTONOMOUS_TRANSACTION 用于标记子程序为自主事务处理

自主事务处理的特征:
    与主事务处理的状态无关
    提交或回滚操作不影响主事务处理
    自主事务处理的结果对其他事务是可见的
    能够启动其他自主事务处理

1.6.2.2.  存储过程中的循环 


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

1.6.2.2.1  for ... in ... loop  循环 
1:循环遍历游标 
示例1: 

猜你喜欢

转载自blog.csdn.net/shangyuanlang/article/details/81915160
1.6