PLSQL–高级编程

  • Post author:
  • Post category:其他

一、存储过程(存过)

1 存储过程的创建

  • 语法
CREATE [OR REPLACE] PROCEDURE 过程名字(SP_NAME) [(参数1,参数2,...)]
IS|AS
  变量名字 变量类型,
  .....
BEGIN
  语句;
  EXCEPTION 
    异常处理;
END [SP_NAME];
  • 例子
-- 编写一个存储过程 判断闰年
CREATE OR REPLACE PROCEDURE SP_YEAR(
       I_YEAR IN  NUMBER,  -- IN 输入参数
       O_YEAR OUT VARCHAR2 -- OUT 输出参数
)
IS 
BEGIN
  IF MOD(I_YEAR,4)=0 AND MOD(I_YEAR,100)<>0 OR MOD(I_YEAR,400)=0 THEN
    O_YEAR := '闰年';
  ELSE
    O_YEAR := '平年';
  END IF;
END SP_YEAR;
  • 注意
可以设置参数的类型,不写的话默认是IN,只需要指定参数的类型,不需要指定参数的长度。

2 存储过程的调用

1) 在块中直接写 存储过程名字(参数值1,参数值2.....)调用;-- 常用于程序自动的调用
DECLARE
  A VARCHAR2(200);
BEGIN
  SP_YEAR(2021,A); -- 输出参数 需要有一个变量来承接输出参数的值  
    -- 没有参数的话 ()可以省略
  DBMS_OUTPUT.PUT_LINE(A);
END;

2) 直接TEST执行存储过程 -- 常用于手动调用程序

3) 在SQL WINDOW中CALL pro_name(para1,para2..)执行(其中就算没有参数括号也不能省略);-- 不带输出参数

4) 在COMMAND WINDOW中使用EXECUTE pro_name(para1,para2..)执行; -- 不带输出参数   
EXECUTE 存储过程名字;
EXEC 存储过程名字;

3 存储过程的参数

1)参数传递的方式
  • 名称传递法
存储过程名字(I_NAME=>VALUE1,I_NAME=>VALUE2....)
  • 位置传递法
存储过程名字(VALUE1,VALUE2...)
  • 混合传递法
存储过程名字(VALUE1,I_NAME2=>VALUE2...)

注意

只有名称传递才能改变参数位置顺序,混合传递中只要使用了名称传递,后续都要使用名称传递。

2)参数的类型
  • IN参数
1) IN模式参数:输入 数据库中默认的一种参数
CREATE OR REPLACE PROCEDURE 存储过程名字 (
 I_NAME1 [IN] DATA_TYPE DEFAULT DEFAULT_VALUE,
 ......
)
IN参数只能是存储默认值或调用方传入值,程序运行过程中IN参数内容不能修改
CREATE OR REPLACE PROCEDURE SP_NYR(
       I_YEAR    VARCHAR2,
       I_MONTH   VARCHAR2,
       I_DAY     VARCHAR2,
       O_NYR OUT VARCHAR2
)
IS
BEGIN
  O_NYR := I_YEAR||'-'||I_MONTH||'-'||I_DAY;
END SP_NYR;

DECLARE 
  B VARCHAR2(10);
BEGIN
  SP_NYR('2021','04','28',B); -- 位置传递法
  DBMS_OUTPUT.PUT_LINE(B);
  SP_NYR(O_NYR=>B,I_YEAR=>'2021',I_DAY=>'28',I_MONTH=>'04');--名称传递法
  DBMS_OUTPUT.PUT_LINE(B);
  SP_NYR('2021',I_DAY=>'28',I_MONTH=>'04',O_NYR=>B);--混合传递法
  DBMS_OUTPUT.PUT_LINE(B);
END;
  • OUT参数
1 实际项目中,OUT参数常常用来返回存储过程的执行状态,比如用0表示执行成功,用1表示执行失败。其他类型的返回内容往往是在后续将要学到的存储函数中出现

2 OUT参数在调用时需要给予相应数量的变量用来接收返回值,所以在调用带有OUT参数的存储过程时,往往是通过TEST窗口或者PL/SQL匿名块来调用。IN OUT 参数类型一样
  • IN OUT参数
定义一个参数  既可以是输入也可以是输出   
IN OUT 参数无论输入和输出,都只有一个数据类型  

CREATE OR REPLACE PROCEDURE SP_DATE(
       IO_DATE IN OUT VARCHAR2
)
IS 
BEGIN
  IO_DATE :='今天的日期是'||IO_DATE;
END SP_DATE;

4 存储过程的删除

DROP PROCEDURE 存储过程名字;
  • 注意

存储过程本身就像一条保存在数据库中的数据,不调用时占用资源很少。

二、存储函数

相对于存储过程,存储函数的数量上、使用频率上都相对较低,源于存储函数必须要有返回值,而且是单一返回值,所以除非特殊功能,多数功能都采用过程来实现。

1 存储函数的创建

  • 语法
CREATE OR REPLACE FUNCTION 函数名字[(参数1 参数类型,参数2 参数类型)]
RETURN 数据类型
AS|IS
  变量名1 变量类型,
  .....
BEGIN
  语句;
  RETURN 变量名;-- 单行单列的结果
  EXCEPTION 
    异常处理语句;
END;
  • 例子
--设计一个存储函数,用于计算每个员工司龄
CREATE OR REPLACE FUNCTION F_HIREDATE (
       I_HIREDATE1    DATE, -- 输入一个日期
       I_HIREDATE2    DATE  :=SYSDATE  -- 输入一个日期或者不输入默认是SYSDATE
       -- I_HIREDATE2 DATE DEFAULT 值
)
RETURN NUMBER
IS
  V_YEARS   NUMBER(10);
BEGIN
  SELECT TO_CHAR(I_HIREDATE2,'YYYY')-TO_CHAR(I_HIREDATE1,'YYYY') INTO V_YEARS FROM DUAL;
  RETURN V_YEARS;
END F_HIREDATE;

-- 设计一个函数,调用时输入薪资和奖金,返回年收入  
CREATE OR REPLACE FUNCTION F_YEAR_INCOME(
       I_SAL   NUMBER,
       I_COMM  NUMBER
)
RETURN NUMBER
IS
  V_INCOME NUMBER;
BEGIN
  V_INCOME := (NVL(I_SAL,0)+NVL(I_COMM,0))*12;
  RETURN V_INCOME;
END F_YEAR_INCOME;


SELECT ENAME,F_YEAR_INCOME(SAL,COMM) FROM EMP;

注意

定义了输出参数的函数,不能在select里面调用

定义了输出参数的函数,可以在块中调用

2 存储函数的删除

DROP FUNCTION 存储函数名字;

三、包

包的组成分为规范和包主体,俗称包头和包体

1 包头

CREATE OR REPLACE PACKAGE PKG_NAME
IS 
  -- 过程的名字和参数信息
  PROCEDURE PRO_NAME(参数1,参数2);
  -- 函数的名字和参数信息
  FUNCTION FUN_NAME(参数1,参数2...) RETURN 数据类型;
  .....
END PKG_NAME;

2 包体

CREATE OR REPLCAE PACKAGE BODY PKG_NAME
IS 
  -- 过程的具体内容
  PROCEDURE PRO_NAME(参数1,参数2...) IS ...;
  -- 函数的具体内容
  FUNCTION FUN_NAME(参数1,参数2...) RETURN 数据类型 IS ...;
  ....
  
END PAK_NAME;

注意

1)包头和包体的名字要相同
2)包头要先于包体建立
3)包头和包体中只有建立包的关键词,没有建立过程、函数等的关键词
4)包头中只需各个程序的名字和参数信息即可,不需要具体内容,而包体中除了名字和参数信息,也要写上具体内容。

包中的过程和一般的过程可以重名 。

3 调用包中的函数和过程

SELECT PKG_RECOVER.F_YEAR(2020) FROM DUAL;

BEGIN
  PKG_RECOVER.SP_RECOVER_DEPT;
  PKG_RECOVER.SP_RECOVER_EMP;
END;

注意

在包的内部调用 可以不加包名,在外面使用需要加上包名,不加上 使用一般的函数 或者存储过程

4 包的删除

DROP PACKAGE PKG_NAME;  

版权声明:本文为c727657851原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。