Oracle -- 存储过程和自定义函数

存储过程和自定义函数

1 . 存储过程和自定义函数的区别:

① 功能不同,存储过程主要用于数据同步,而自定义函数主要用于做计算。

② 调用方式不同,存储过程一般使用 BEGIN END 调用,而自定义函数是放在 SELECT 语句后面调用的。

③ 返回值不同, 存储过程不需要返回结果,而自定义函数必须返回一个计算结果。

④ 定义时不同,存储过程不需要指明返回值的数据类型,自定义函数必须指定返回值的数据类型。

2 . 创建存储过程和自定义函数的语法:

①创建存储过程语法规则:

CREATE OR REPLACE PROCEDURE SP_过程名(参数1 [IN|OUT|IN OUT] 数据类型,
                                    参数2 [IN|OUT|IN OUT] 数据类型…)
IS   /*|AS*/
BEGIN  
  执行体
END ;

②创建自定义函数语法规则:

CREATE OR REPLACE FUNCTION FUN_函数名(参数1 数据类型,
                                     参数2[IN|OUT|IN OUT] 数据类型……)
RETURN 返回的数据类型,不写长度
IS   /*|AS*/
BEGIN  
   执行体
   RETURN  结果; --里面必须要有一个RETURN子句
END ; 

3. 过程和函数的参数类型 [IN|OUT|IN OUT]

IN 类型为 输入参数,默认参数,可以不写。【不能重新赋值】
OUT 类型为 输出参数。【可以被重新赋值,但是不会接受输入的参数】
IN OUT 类型为输入输出参数,既可以接受传入的值,也可以作为输出参数输出结果。【可以被重新赋值】

------------------------------------------ IN 参数 ----------------------------------------------

  1. 定义一个存储过程 使用 in 参数类型实现,
    接收员工的 编号,打印出员工的 入职时间和社保缴纳日期,显示为字符格式 (YYYY-MM)

① 创建存储过程

CREATE OR REPLACE PROCEDURE SP_EMP(P_EMPNO IN NUMBER)
IS
   V_HD  DATE;--入职时间
   V_JD  VARCHAR2(8);--社保缴纳时间
BEGIN
   SELECT E.HIREDATE , --入职时间
          TO_CHAR( ROUND(E.hiredate,'MM')  ,'YYYY-MM') JD --社保缴纳时间
   INTO V_HD ,V_JD
   FROM  EMP E
   WHERE E.EMPNO =  P_EMPNO;--传入员工编号

   DBMS_OUTPUT.PUT_LINE(TO_CHAR(V_HD,'YYYY-MM-DD')||' '||V_JD);
END ;

② 调用存储过程

BEGIN 
  SP_EMP(7369);
END ;
  1. 定义一个自定义函数 使用 in 参数类型实现,
    接收员工的 编号,返回员工的社保缴纳日期,显示为字符格式 (YYYY-MM)

① 自定义函数

CREATE OR REPLACE FUNCTION FUN_EMP(P_EMPNO IN NUMBER)
RETURN   VARCHAR2
IS 
  V_JD  VARCHAR2(8);--社保缴纳日期
BEGIN  
  SELECT TO_CHAR( ROUND(E.hiredate,'MM')  ,'YYYY-MM') 
  INTO V_JD
  FROM EMP E
  WHERE E.empno = P_EMPNO;
  
  RETURN V_JD;
END ;

② 调用自定义函数

SELECT E.* ,
       FUN_EMP(E.empno) 社保缴纳年月
FROM EMP E;

------------------------------------------ OUT 参数 ---------------------------------------------

OUT****类型为 输出参数。【可以被重新赋值,但是不会接收任何 传入/输入的值】
并且,一旦定义了 OUT 类型的参数,调用过程时,必须传入一个 变量,不传会报错。

①创建存储过程

CREATE OR REPLACE PROCEDURE SP_HELLOWORLD (P_STR  OUT VARCHAR2)
IS 
BEGIN 
  P_STR := '不听不听,除非买包';
  DBMS_OUTPUT.PUT_LINE('HELLO WORLD');
  DBMS_OUTPUT.PUT_LINE('HELLO '||P_STR);
END ;

②调用存储过程

DECLARE
  V_STR  VARCHAR2(30) := '包太贵,买口红吧' ;
BEGIN 
  SP_HELLOWORLD(V_STR);
END ;

在这里插入图片描述

---------------------------------------------- IN OUT 参数 ----------------------------------------------

IN OUT 类型的参数,既可以接收传入的值 ,又可以把该参数作为 输出的对象

比如 接收员工的姓名,打印出该员工的 岗位

①创建存储过程

CREATE OR REPLACE PROCEDURE  SP_ENAME_JOB(P_NAME_JOB IN  OUT VARCHAR2)
IS 
   -- 这里不需要单独定义输出的变量。因为可以对 输入输出参数重新赋值。
BEGIN 
  SELECT JOB 
  INTO  P_NAME_JOB   -- 对 out 类型的参数进行重新赋值,并最后打印出来
  FROM EMP 
  WHERE ENAME = P_NAME_JOB;   -- 使用参数接收的姓名作为条件
  
  DBMS_OUTPUT.PUT_LINE(P_NAME_JOB);
END ;

②调用存储过程

DECLARE
  V_ENAME  VARCHAR2(10) :='SCOTT';
BEGIN 
  SP_ENAME_JOB(V_ENAME);
END ;

对比 IN 和 IN OUT 类型的参数

①创建存储过程

CREATE OR REPLACE PROCEDURE  SP_JOB(P_NAME  VARCHAR2)
IS 
   V_JOB  VARCHAR2(10);
BEGIN 
  SELECT JOB
  INTO V_JOB
  FROM EMP 
  WHERE ENAME = P_NAME;
  DBMS_OUTPUT.PUT_LINE(V_JOB);
END ;

②调用存储过程

BEGIN 
  SP_JOB('SCOTT');
END ;

【例】查询20部门中的经理的姓名、工资、入职日期。

①创建存储过程

CREATE OR REPLACE PROCEDURE SP_MYEMP( P_DEPTNO   IN NUMBER,
                                     P_HIREDATE  OUT DATE,
                                     P_JOB_ENAME IN OUT VARCHAR2) 
AS
                                       ----------参数不能定义长度
  V_SAL NUMBER;--声明变量V_SAL
BEGIN
  SELECT E.ENAME,--姓名      
         E.SAL,  --工资
         E.HIREDATE --入职日期
    INTO P_JOB_ENAME, -- P_JOB_ENAME 这里是姓名
         V_SAL,   
         P_HIREDATE 
    FROM EMP E
   WHERE E.DEPTNO = P_DEPTNO
     AND E.JOB = P_JOB_ENAME;  -- P_JOB_ENAME 是岗位
  DBMS_OUTPUT.PUT_LINE(P_JOB_ENAME || ' ' || V_SAL || ' ' ||       TO_CHAR(P_HIREDATE,'YYYY/MM/DD'));
END;

②调用存储过程

DECLARE
   V_date DATE;--OUT类型,声明变量传入参数
   V_JOB  VARCHAR2(10) :='MANAGER';
BEGIN
  SP_MYEMP(20,V_date,V_JOB);
END ;

总结:

  1. 在过程或者函数中定义了参数,就必须传值
  2. IN 类型的参数,不能通过变量传值,必须直接传值[可以是数字 字符 日期
  3. 带了 OUT 类型的参数,必须通过变量传参,无论是 OUT 或者 IN OUT
  4. OUT 类型的参数,虽然不接收传入的参数,但是跟第一条一样,必须给它一个变量,哪怕变量的值是空的。
  5. IN OUT 类型的参数,也需要通过变量传参,同时 IN OUT 类型的参数,可以像变量一样输出或者被重新赋值。
发布了28 篇原创文章 · 获赞 3 · 访问量 6846

猜你喜欢

转载自blog.csdn.net/ferlylao/article/details/104091740
今日推荐