Oracle --函数,包

/*
函数语法:
 CREATE[OR REPLACE]FUNCTION<>
        (<参数1>,[方式1],<数据类型1>,<参数2>,[方式2]<数据类型2>...)
  RETURN<表达式>
  IS|AS
  PL/SQL 程序体  --其中必须要有一个RETURN子句
  
 其中,RETURN在声明部分需要定义一个返回参数的类型,而在函数体中必须有一个
 RETURN语句,而其中<表达式>就是要函数返回的值,当该语句执行时,如果表达式
 的类型和定义不符,该表达式将被转换成函数定义子句RETURN中指定的类型。
 同时,控制将立即返回调用环境,但是,函数中可以有一个以上的返回语句,如果
 如果函数结束时还没有遇到返回语句,就会发生错误。
 通常,函数只有in类型的参数
*/
--1. 根据部门编号得到该部门的平均工资
 create or  replace  function get_avg(dept_no number) return number
 is
    avgsal number;
  begin
   select avg(sal) into avgsal  from emp where deptno=dept_no;
   return avgsal;
  exception
    when no_data_found then
     raise_application_error(-20001,'无此部门');
 end;
 
 --两种方式调用 PL/SQL
 DECLARE
     DEPT_NO NUMBER := '&DEPTNO';
     RETURN_NUMBER NUMBER;
 BEGIN
     RETURN_NUMBER := ROUND(GET_AVG(DEPT_NO);
     DBMS_OUTPUT.PUT_LINE(RETURN_NUMBER);
 END;
 --SELECT 语句调用函数
 select get_avg(20) "20号部门的平均工资" from dual; 
 -- 测试,查询工资大于自己部门平均工资的员工信息
 select e.*,get_avg(deptno) 部门平均工资  from emp e  where sal > get_avg(deptno);
 
 --2. 根据部门编号和职务得到员工人数
 create or  replace  function get_num(p_deptno number, p_job varchar2) return number
 is
    num_count number; --人数
  begin
   select count(*) into num_count from emp where deptno = p_deptno and job = p_job;
   return num_count;
 end;
 --调用函数
 select deptno 部门编号, job 职务,get_num(deptno, job) 人数 from emp group by deptno,job 
 order by deptno; 
--删除函数
drop function get_num;
/*
程序包规范创建语法如下:
      CREATE OR REPLACE PACKAGE package_name
      IS | AS      
         公用类型或变量常量的声明;
         公用过程或函数的声明;
      END;
     包主体部分创建语法如下:
      CREATE OR REPLACE PACKAGE BODY package_name
      IS | AS       
          私有类型或变量常量的声明;
          公用过程或函数的实现;
      END;
*/
--示例1:包的定义
create or replace  package mypackage
 is
   -- 声明常量 
   PI constant number :=3.14;
    -- 声明(获取圆周长)函数
   function get_area_perimeter(radius number) return number;
   -- 声明(输出hello的)存储过程     
   procedure say_hello(pname varchar2); 
  
end;

--包主体定义
create or replace package body mypackage
 as 
   function get_area_perimeter(radius number) return number --定义函数的实现
    is 
       perimeter number:=0; --周长
    begin 
       perimeter:= 2 * mypackage.PI * radius;
       return perimeter;
   end;
   procedure say_hello(pname varchar2) --定义存储过程的实现    
   is 
    begin 
         dbms_output.put_line('HELLO WORLD '||pname);
    end;
end;
-- 包的使用
declare
begin
  mypackage.say_hello('潭州'); -- 执行存储过程
end;
--调用函数
select mypackage.get_area_perimeter(2) from dual; 

--示例2:包中游标的使用
create or replace package mypackage2
 is
      /*
         return: 
         1、可以使用,也可以不使用。
         2、如果使用了return,则表示已经有了某类型,所以就可以在后面引用这个游标的行集类型。
         3、如果没有return,则表示没有类型,则后面必须自己一个行集类型。
      */
     type emp_cur is ref cursor return emp%rowtype;
     --根据部门编号查询部门信息
     procedure query_emp(pdeptno number, ec out emp_cur);
 end;
 
 create or replace package body mypackage2
 is
    procedure query_emp(pdeptno number, ec out emp_cur)
      is
      begin
          open ec for select * from emp where deptno = pdeptno;   
      end;          
 end;
 
 --存储过程的调用
 declare
   ec mypackage2.emp_cur; --定义一个引用游标
   rec ec%rowtype;
 begin  
   mypackage2.query_emp(20, ec);
   fetch ec into rec; 
   while(ec%found)
   loop
      dbms_output.put_line(rec.empno ||','||rec.ename||','||rec.job||','||rec.deptno);
      fetch ec into rec; 
   end loop;
   close ec;
 end;

--查看包的信息
  
select object_name ,object_type from user_objects
   where  object_type in ('PROCEDURE','FUNCTION','PACKAGE','PACKAGE BODY');

--删除包
drop package mypackage;

猜你喜欢

转载自blog.csdn.net/mao502010435/article/details/81480285