/*
函数语法:
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;