PL/SQL存储过程、存储函数、异常

存储过程、存储函数、异常

  • 一、存储过程
      • 1.存储过程的概述
      • 2.存储过程的创建语法
  • 二、存储函数
      • 1.认识存储函数
      • 2.存储函数的创建
  • 三、异常处理
      • 1.异常处理的分类
      • 2.异常处理创建

一、存储过程

1.存储过程的概述

简称“存储”或者“存过”,是一种命名的PL/SQL程序。存储过程会依据输入参数来决定程序如何运行,而且在调用结束时,存储过程还可根据程序运行情况返回一些输出参数

2.存储过程的创建语法

①语法

--------------存储过程---------------
CREATE [OR REPLACE] PROCEDURAL PRO_NAME [(PARA1,PARA2...)]
AS|AS
  VAR_NAEM VAR_TYPE;
  ...
BEGIN
  PLSQL_SENTENCE
  EXCEPTION
    EXCEPT_SENTENCE
END [PRO_NAME];

--CREATE创建过程 OR REPLACE 替换一个过程

②编译
存储过程代码写完后需要点击执行,执行的是编译的过程,也就是写入数据库的过程,编译后的存储过程可以在工具的左侧产看编译状态。有问题会出现 “x” 号。
注意

  1. 类似表索引,过程也是有自己的用户所属;
  2. 过程上的X号不一定真的有问题,可以尝试重新编译
  3. 有问题的过程可以在edit界面调试改正

注意 : 存储过程中的DDL语句权限问题:数据库当前用户授予了connect、resource权限,在存储过程里面执行execute immediate 'create table XX’时会报“权限不足”的错误。resource角色是具有create table的权限的,为什么在存储过程里面创建表就权限不足了。原因为:用户拥有的角色role在存储过程里面不可用必须授予一个一个的权限才会起作用即不能授予角色

解决办法:

  1. 给当前用户授权:==grant create table to user;
  2. 创建存储过程的时候加上authid current user
    create or replace procedure xx authid current user is
    ②执行
    三种方法:
    (1)call pro_name();
    (2)sqlplus 中执行execute pro_name ;
    (3)begin table_rebuiled_emp; end;
    ③参数in、out、in out

对于形式参数的约束:在过程或者函数的声明中char、varchar2的长度以及number的范围,精度都是非法的

(1)IN模式参数
语法

--in模式参数

CREATE OR REPLACE PROCEDURE PRO_NAME(
   I_NAME1 [IN] DATA_TYPE DEFAULT DEF_VAL,
   I_NAME2 [IN] DATA_TYPE DEFAULT DEF_VAL,
   ...
)
IS|AS

--可以设置默认值,供无实参录入时使用
-- in参数只能存储默认值过或方法传值

--存储过程-参数传递方法
--名称传递
PRO_NAME(I_NAME1=>,I_NAME2,...)
--位置传递
pro_name(value1,value2)
--混合传递法
pro_name(value1,i_name2=>value2)

--注意只有名称传递才能更改原参数位置顺序
--混合传递法中但凡某位置用了名称传递,后续都要用名称传递

(2)out模式参数 --一般不用
代码实现:

--out模式参数:输出类型的参数 一般不用
CREATE OR REPLACE PROCEDURE
SP_EMP_SAL(V_RATE NUMBER,V_NAME VARCHAR2,V_SAL OUT NUMBER)
IS
BEGIN
  UPDATE EMP SET SAL=SAL*(1+V_RATE) WHERE ENAME=V_NAME;
  COMMIT;
  SELECT SAL INTO V_SAL FROM EMP WHERE ENAME=V_NAME;
END SP_EMP_SAL;

DECLARE
  A NUMBER;
BEGIN
  SP_EMP_SAL(0.5,'SMITH',A);
  DBMS_OUTPUT.PUT_LINE(A);
END;

(3)in out 参数模式
代码实现:

-- IN OUT 模式参数

CREATE OR REPLACE PROCEDURE
   SP_EMP_SAL(V_RATE IN OUT NUMBER,V_NAME VARCHAR2)
   IS
   
BEGIN
  UPDATE EMP SET SAL=SAL*(1+V_RATE) WHERE ENAME=V_NAME;
  COMMIT;
  SELECT SAL INTO V_RATE FROM EMP WHERE ENAME=V_NAME;
END SP_EMP_SAL;

DECLARE
    V_RATE NUMBER:=0.5;
    V_NAME VARCHAR2(300):='SMITH'; 
BEGIN
  SP_EMP_SAL(V_RATE,V_NAME);
  DBMS_OUTPUT.PUT_LINE(V_RATE);
END;

④删除存储过程
drop procedure 存储过程名

二、存储函数

1.认识存储函数

存储函数与存储过程语法很相似,区别:

  1. 函数的关键字function
  2. 只有一个返回值类型,要只用return关键字单独声明
  3. 程序中要使用return关键字指明返回结果,返回结果与声明的返回值类型保持一致
  4. 函数一般是为了完成某个功能加工后的结果,一般不会在函数中创建delete 、updata等dml语句
  5. 如果要写dml在声明后面加PRAGMA AUTONOMOUS_TRANSACTION

2.存储函数的创建

语法:

CREATE [OR REPLACE] FUNCTION FUN_NAME [(PARA1,PARA2...)]
RETURN DATATYPE
AS|IS
    VAR_NAME VAR_TYPE;
    ...
BEGIN
  PLSQL_SENTENCE
  RETURN VAR_NAME;
  EXCEPTION
    EXCEPT_STENTENCE
END [FUN_NAME];

调用
select fun_name(para) from dual;
删除
drop function fun_name;

三、异常处理

官方角度
PL/SQL存储过程、存储函数、异常_第1张图片
用户角度
PL/SQL存储过程、存储函数、异常_第2张图片

1.异常处理的分类

  • 预定义异常:数据库判定
  • 非预定义异常:数据判定,需要给名称后才能被异常处理部分捕捉
  • 自定义:业务逻辑判定,本省不存在

2.异常处理创建

结构

EXCEPTION
  WHEN ERR_NAME1 TEHN
    EXCEPT_SENTENCE1
  WHEN ERR_NAME2 TEHN
    EXCEPT_SENTENCE
    ...
  WHEN OTHERS TEHN
    EXCEPT_SENTENCEN

预定义

BEGIN
  plsql_sentence
  EXCEPTION
    WHEN ERR_NAEM THEN
      EXCEPT_SENTENCE
END;
--预定义异常在使用时完全不需要用户声明,由ORACLE自行引发自行判定

代码实现:

DECLARE
  A  EMP.ENAME%TYPE;
BEGIN
  DBMS_OUTPUT.PUT_LINE('程序执行开始......');
  SELECT ENAME INTO A FROM EMP WHERE DEPTNO=60;
  DBMS_OUTPUT.PUT_LINE(A);
  EXCEPTION 
       WHEN TOO_MANY_ROWS  THEN
       DBMS_OUTPUT.PUT_LINE('试图将多个数据赋给一个变量');
       WHEN NO_DATA_FOUND  THEN
       DBMS_OUTPUT.PUT_LINE('没有任何数据');
       WHEN OTHERS THEN
       DBMS_OUTPUT.PUT_LINE('程序出错!');
     --  RAISE; -- 将发生的异常以原来默认弹框显示
END;

非预定义异常

DECLARE
  ERR_NAEM EXCEPTION;
  REAGME EXCEPTION_INIT(ERR_NAME,ERR_CODE);
BEGIN
  PLSQL_SENTENCE
  EXCEPTION
    WHEN ERR_NAME THEN
      EXCEPT_SENTENCE
END;

代码实现:

DECLARE
  -- 1.定义非预定义异常
  E_FK EXCEPTION;
  -- 2.把ORACLE错误与异常建立关联
  --  -2292 违反外键约束的错误编号
  PRAGMA EXCEPTION_INIT(E_FK,-2292);
BEGIN
  DELETE FROM DEPT WHERE DEPTNO = &DEPTNO;
  EXCEPTION
    WHEN E_FK THEN
       -- 3.捕捉并处理异常
      DBMS_OUTPUT.PUT_LINE('此部门下有员工,无法删除!');
    WHEN OTHERS THEN
      -- SQLCODE 获得ORACLE错误编号,SQLERRM获取ORACLE错误信息
      DBMS_OUTPUT.PUT_LINE(SQLCODE||'###'||SQLERRM);
END; 

自定义异常

DECLARE
  ERR_NAME EXCEPTION;
BEGIN
  IF <CONDITION_EXPRESSION1> THEN
    RAISE ERR_NAME;
  END IF;
  PLSQL_SENTENCE
  EXCEPTION
    WHEN ERR_NAME THEN 
      EXCEPT_SENTENCE
END;

注意

  1. RAISE err_name 转到异常处理部分;
    RAISE_APPLICATION_ERROR(err_code,err_mess),引发弹窗报错。
    err_code:自定义错误编号,限制在-20001到-20999之间
    err_mess:自定义错误信息,字符型内容

代码实现

--自定义异常 不对异常进行处理要处理必须为异常起名字
DECLARE
   V_COMM EMP.COMM%TYPE;
BEGIN
   SELECT COMM INTO V_COMM FROM EMP WHERE EMPNO=7788;
   IF V_COMM IS NULL THEN
      RAISE_APPLICATION_ERROR('-20010','该雇员无补助');
   END IF;
END;


--自义定异常
DECLARE
   V_COMM EMP.COMM%TYPE;
   E_COMM_IS_NULL EXCEPTION;--定义异常类型变量
BEGIN
   SELECT COMM INTO V_COMM FROM EMP WHERE EMPNO=7788;
   IF V_COMM IS NULL THEN
      RAISE E_COMM_IS_NULL;  -- 抛出一个自定义异常,如果发生异常就会调转到EXCEPTION部分
   END IF;
EXCEPTION
   WHEN NO_DATA_FOUND THEN
     DBMS_OUTPUT.PUT_LINE('雇员不存在!错误为:'||SQLCODE||SQLERRM);
   WHEN E_COMM_IS_NULL THEN   --处理自定义异常
     DBMS_OUTPUT.PUT_LINE('该雇员无补助 ');
   -- RAISE_APPLICATION_ERROR(-20001,'该员工没有奖金'); --为异常绑定一个编号并 以弹窗形式弹出错误信息
END;

你可能感兴趣的:(数据库,sql,oracle,数据库)