Oracle进阶(二)存储过程

目录

1、名词释义

2、创建语法

3、系统异常

4.1、无参存储过程

4.2、带参数存储过程

4.3、带if的存储过程

4.4、带if else的存储过程

4.5、带else if的存储过程

4.6、带while循环的存储过程

4.7、带select into的存储过程

1、名词释义

存储过程(Stored Procedure)是一组为了完成特定功能的SQL语句集,是由流程控制和SQL语句书写的命名语句块。
Oracle存储过程包含三部分:过程声明,执行过程部分,存储过程异常。

2、创建语法

CREATE [OR REPLACE] PROCEDURE 存储过程名(PARAM1 IN TYPE,PARAM2 OUT TYPE)
AS   --as和is任选一个,在这没有区别
变量1 类型(值范围);
变量2 类型(值范围);
BEGIN
    SELECT COUNT(*) INTO 变量1 FROM 表A WHERE列名=PARAM1;

    IF (判断条件) THEN
       SELECT 列名 INTO 变量2 FROM 表A WHERE列名=PARAM1;
       DBMS_OUTPUT.PUT_LINE(‘打印信息’);
    ELSIF (判断条件) THEN
       DBMS_OUTPUT.PUT_LINE(‘打印信息’);
    ELSE
       RAISE 异常名(NO_DATA_FOUND);
    END IF;
EXCEPTION
    WHEN OTHERS THEN
       ROLLBACK;
END;

3、系统异常

ACCESS_INTO_NULL 未定义对象
CASE_NOT_FOUND CASE 中若未包含相应的 WHEN ,并且没有设置ELSE 时
COLLECTION_IS_NULL 集合元素未初始化
CURSER_ALREADY_OPEN 游标已经打开
DUP_VAL_ON_INDEX 唯一索引对应的列上有重复的值
INVALID_CURSOR 在不合法的游标上进行操作
INVALID_NUMBER 内嵌的 SQL 语句不能将字符转换为数字
NO_DATA_FOUND 使用 select into 未返回行,或应用索引表未初始化的
TOO_MANY_ROWS 执行 select into 时,结果集超过一行
ZERO_DIVIDE  除数为 0
SUBSCRIPT_BEYOND_COUNT 元素下标超过嵌套表或 VARRAY 的最大值
SUBSCRIPT_OUTSIDE_LIMIT 使用嵌套表或 VARRAY 时,将下标指定为负数
VALUE_ERROR 赋值时,变量长度不足以容纳实际数据
LOGIN_DENIED PL/SQL 应用程序连接到 oracle 数据库时,提供了不正确的用户名或密码
NOT_LOGGED_ON PL/SQL 应用程序在没有连接 oralce 数据库的情况下访问数据
PROGRAM_ERROR PL/SQL 内部问题,可能需要重装数据字典& pl./SQL系统包
ROWTYPE_MISMATCH 宿主游标变量与 PL/SQL 游标变量的返回类型不兼容
SELF_IS_NULL 使用对象类型时,在 null 对象上调用对象方法
STORAGE_ERROR 运行 PL/SQL 时,超出内存空间
SYS_INVALID_ID 无效的 ROWID 字符串
TIMEOUT_ON_RESOURCE Oracle 在等待资源时超时

 

4.1、无参存储过程

--1)无参存储过程语法

CREATE OR REPLACE PROCEDURE PRO_1_NOPAR
 AS --声明
 
 BEGIN --执行
	 --SELECT * FROM D_DEPT D;
DBMS_OUTPUT.PUT_LINE('无参存储过程');
 EXCEPTION--异常
    WHEN OTHERS THEN
       ROLLBACK;
 END;

--调用
BEGIN
  PRO_1_NOPAR;
END;

4.2、带参数存储过程

IN表示输入参数,是参数的默认模式。
OUT表示返回值参数,类型可以使用任意Oracle中的合法类型。
OUT模式定义的参数只能在过程体内部赋值,表示该参数可以将某个值传递回调。
IN OUT表示该参数可以向该过程中传递值,也可以将某个值传出去。

--2)带参数存储过程含赋值方式
CREATE OR REPLACE PROCEDURE PRO_2_PAR   
    (VAL IN NUMBER,   
     SNAME OUT VARCHAR,  
     DT_CODE IN OUT VARCHAR)  
 AS   
    ICOUNT NUMBER;  
 BEGIN  
      SELECT COUNT(*) INTO ICOUNT FROM D_DEPT WHERE DT_ID>VAL;  
      IF ICOUNT=1 THEN  
        SNAME:= 'MLB事业部1' ||VAL;
				DT_CODE:= 'MLB1'||DT_CODE;
      ELSE  
      SNAME:= 'MLB事业部2'||VAL;
				DT_CODE:= 'MLB2'||DT_CODE;
     END IF;  
EXCEPTION  
     WHEN TOO_MANY_ROWS THEN  
     DBMS_OUTPUT.PUT_LINE('返回值多于1行');  
     WHEN OTHERS THEN  
     DBMS_OUTPUT.PUT_LINE('在PRO_1_PAR过程中出错!');  
END;  

--调用
declare  
     REVAL NUMBER;  
     RENAME varchar(40);  
     RECODE varchar(40);  
begin    --过程调用开始  
     REVAL:=20210421;  
     RENAME:='';  
     RECODE:='JUNIOR';  
     --指定值对应变量顺序可变  
     PRO_2_PAR(SNAME=>RENAME,VAL=>REVAL,DT_CODE=>RECODE);           
    DBMS_OUTPUT.PUT_LINE(RENAME||'   '||RECODE);  
END;  --过程调用结束

4.3、带if的存储过程

--3)带if的存储过程
CREATE OR REPLACE PROCEDURE PRO_3_IF(A IN NUMBER, B IN NUMBER,RS OUT NUMBER)
AS
    TEMP NUMBER;
BEGIN
    TEMP:=A;
    IF A < B THEN
        TEMP := B;
    END IF;
    RS:=TEMP;
END;

--调用
DECLARE
    RS NUMBER;
BEGIN
    PRO_3_IF(10,20,RS);
    DBMS_OUTPUT.PUT_LINE('RS='||RS);
END;

4.4、带if else的存储过程

CREATE OR REPLACE PROCEDURE PRO_4_IFELSE(A IN NUMBER, B IN NUMBER,RS OUT NUMBER)
AS
BEGIN
    IF A > B THEN
        RS := A;
    ELSE
        RS := B;
    END IF;
END;

--调用
DECLARE
    RS NUMBER;
BEGIN
    PRO_4_IFELSE(30,20,RS);
    DBMS_OUTPUT.PUT_LINE('RS='||RS);
END; 

4.5、带else if的存储过程

CREATE OR REPLACE PROCEDURE PRO_5_ELSEIF(Y IN NUMBER)
AS
BEGIN
    IF Y=2020 THEN
        DBMS_OUTPUT.PUT_LINE('2020年');
    ELSIF Y =2021 THEN
        DBMS_OUTPUT.PUT_LINE('2021年');
    ELSE
        DBMS_OUTPUT.PUT_LINE('未知年份');
    END IF;
END;

--存储过程调用
BEGIN
  PRO_5_ELSEIF(Y => 2021);
END;

4.6、带while循环的存储过程

--6)带while循环的存储过程
CREATE OR REPLACE PROCEDURE PRO_6_WHILE(I IN NUMBER)
AS
    J NUMBER;
BEGIN
    J := 1;
    WHILE J <= I LOOP
        DBMS_OUTPUT.PUT_LINE('J='||J);
        J := J + 1;
    END LOOP;
END;

--存储过程调用
BEGIN
  PRO_6_WHILE(I=> 100);
END;

4.7、带select into的存储过程

在利用SELECT…INTO…语法时,必须先确保数据库中有该条记录,否则会报出"NO_DATA_FOUND"异常。
可先利用SELECT COUNT(*) FROM 查看数据库中是否存在该记录,存在则使用SELECT…INTO。
在存储过程中,别名不能和字段名称相同,否则虽然编译可以通过,但在运行阶段会报错。

--7)带SELECT INTO的存储过程
CREATE OR REPLACE PROCEDURE PRO_7_SELINTO(ID IN NUMBER)
AS
M VARCHAR(50);
G VARCHAR(50);
BEGIN
  SELECT MONTH,ORG_OID INTO M,G FROM D_DEPT where DT_ID=ID;
   DBMS_OUTPUT.PUT_LINE('M'||M||'G'||G);
  EXCEPTION
  WHEN NO_DATA_FOUND THEN
      DBMS_OUTPUT.PUT_LINE('NO_DATA_FOUND异常');
END;


--存储过程调用
BEGIN
  PRO_7_SELINTO(ID=> 21);
END;

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