PLSQL 层层嵌套,自定义函数

匿名块
declare
begin
exception
end;


--exception   异常
┌预定义异常          --系统给的,有名字
├非预定义异常        --系统给的,没有名字
└用户自定义异常      --用户自己定义的

为什么要处理异常?
由于plsql程序块一旦产生异常而没有指出如何处理时,程序会自动终止。
异常情况处理就是用来处理这些正常执行中未预料到的事件。

--预定义异常      (不用声明)
┌违反唯一性限制     dup_val_on_index    
├没有找到数据       no_date_found
├返回多行           too_many_rows
├试图用0作除数      zero_divide
└其他异常           others


--键盘输入一个员工姓名,打印员工编号,输入一个部门编号,打印员工编号
declare
v_ename varchar2(20):=&a;
v_empno number;
v_deptno number:=&b;
begin
  select empno into v_empno
  from emp
  where ename=v_ename;
  
  dbms_output.put_line(v_empno);
  
  select empno into v_empno
  from emp
  where deptno=v_deptno;
  
  dbms_output.put_line(v_empno); 
exception
 when too_many_rows then
    dbms_output.put_line(sqlcode||' '||sqlerrm);
  when no_data_found then
    dbms_output.put_line(sqlcode||' '||sqlerrm);
  when others then 
    dbms_output.put_line(sqlcode||' '||sqlerrm);
end;


错误描述:sqlcode
错误代码:sqlerrm

--非预定义异常

--向emp表插入一条数据

declare
err exception;     --声明异常
err2 exception;
pragma exception_init(err,-2291);     --把-2291这个预定义异常赋给err
pragma exception_init(err2,-00001); 
begin
  insert into emp(deptno,empno) values(50,7788);
exception
  when err then
    dbms_output.put_line(sqlcode||' '||sqlerrm);
  when err2 then 
    dbms_output.put_line(sqlcode||' '||sqlerrm);
end;

--用户自定义异常

--向emp1插入一条员工编号,要求员工编号必须为7开头且四个数字
declare
v1 number:=&a;
err exception;     --声明异常
begin
  
  if v1 not like '7___' then raise err;     --抛出一样
  else insert into emp1(empno) values(v1);
  end if;
exception
  when err then
    dbms_output.put_line('请输入7开头且四位的员工编号');  
    raise_application_error(-20001,'员工编号不规范');    --弹窗报错 
end;


raise_application_error(错误代码,错误描述)
错误代码:-20000到-20999

--emp1表和emp表格式一样.向emp1插入一条empno,sal,job
--要求empno必须是4位数字并且7开头,工资必须大于3000,工作不能为空
--如果不合规定,弹窗报错"...必须..."

declare
err1 exception;
err2 exception;
err3 exception;
v1 number:=&a;
v2 number:=&b;
v3 varchar2(20):=&c;
begin
  if v1 not like '7___' then raise err1;
  elsif v2 <=3000 then raise err2;
  elsif v3 is null then raise err3;
  else insert into emp1(empno,sal,job) values(v1,v2,v3);
  end if;
exception
  when err1 then
    raise_application_error(-20001,'员工编号必须7开头且为4位');
  when err2 then
    raise_application_error(-20002,'工资必须大于3000');
  when err3 then   
   raise_application_error(-20003,'职位必须不能为空');
end;

--层层嵌套和子块并列
程序的执行分为两种情况
串行:本次程序的运行依赖于上一个程序的运行结果,如果上一个程序出错,
     本次程序不会运行,肯定是错的.
并行:两个程序之间没有关系,可能只是为了运行方便或者业务的要求将两个
     程序放在一起执行,一个程序出错,不会影响另一个.

--层层嵌套
declare
v_外 varchar2(20):='外';
begin
  declare
  v_中 varchar2(20):='中';
  v_empno number:=&a;
  v_ename varchar2(20);
  begin
    declare
    v_内 varchar2(20):='内';
    begin
      dbms_output.put_line(v_内);
    exception
    when no_data_found then
      dbms_output.put_line('错了');
    end;
    dbms_output.put_line(v_中);
      select ename into v_ename
      from emp
      where empno=v_empno;    
  end;
  dbms_output.put_line(v_外);

end;

·内层可以用外层的变量,外层不能用内层的变量
·内层可以用外层的异常,外层不能用内层的异常
·如果内层发生异常,从内向外抛出异常


--子块并列
declare
v_外 varchar2(20):='外';
begin
  declare
  v_内1 varchar2(20):='内1';
  begin
    dbms_output.put_line(v_内1);
  end;
  
  declare
  v_内2 varchar2(20):='内2';
  begin
    dbms_output.put_line(v_内2);
  end;
   dbms_output.put_line(v_外);
end;


·子块之间不能用彼此的变量,也不能用彼此的异常
·子块都可以用外层的变量和异常
·层层嵌套和子块并列可以联合使用形成综合结构


--emp1表和emp表格式一样.向emp1插入一条empno,sal,job
--要求empno必须是4位数字并且7开头,如果不符合,将empno处理成7000插入
--工资必须大于3000,如果不符合,将工资处理成3000插入
--工作不能为空,如果不符合,将工作处理成CLERK插入

declare
v_empno number:=&a;
v_sal number:=&b;
v_job varchar2(20):=&c;
err exception;
begin
  begin
    if v_empno not like '7___' then raise err;
    else insert into emp1(empno)values(v_empno);
    end if;
  exception
    when err then
    insert into emp1(empno)values(7000);
  end;
  
  begin
    if v_sal<=3000 then raise err;
    else insert into emp1(sal)values(v_sal);
    end if;
  exception
    when err then 
      insert into emp1(sal)values(3000);
  end;
  
  begin
    if v_job is null then raise err;
    else insert into emp1(job)values(v_job);
    end if;
  exception
    when err then 
      insert into emp1(job)values('CLERK');
  end;
end;


--自定义函数     function      有名块
create [or replace] function 函数名(参数 [in]|out 类型,参数2..) return 返回值类型
is
声明;
begin
  执行部分;
[exception]
异常部分
end;


--制作一个函数my_sign
create or replace function my_sign(v1 in number) return number
is
begin
  if v1>0 then return 1;
  elsif v1<0 then return -1;
  elsif v1=0 then return 0;
  end if;
end;


--制作一个函数my_xfs,输入一个数字返回他的相反数
create or replace function my_xfs(v1 number) return number
is
begin
   return -v1;
end;

--制作一个函数my_jdz,输入一个数字返回他的绝对值
create or replace function my_jdz(v1 number) return number
is
begin
  if v1>0 then return v1;
  elsif v1<0 then return -v1;
  else return 0;
  end if;
end;


select my_jdz(-5)
from dual

--制作一个函数,表示π 
create or replace function π return number
is
begin
  return 3.14;
end;


select π
from dual


--查询半径是2的圆的面积
select π*power(2,2)
from dual


--查询半径是2的球的体积
select 4/3*π*power(2,3)
from dual

--制作一个函数,输入三个数字,反回最大的那个数字
create or replace function f1(v1 number,v2 number,v3 number) return number
is
begin
  if v1>=v2 and v1>=v3 then return v1;
  elsif v2>=v1 and v2>=v3 then return v2;
  elsif v3>=v1 and v3>=v2 then return v3;
  end if;
end;

create or replace function f1_1(v1 number,v2 number,v3 number) return number
is
v_m number;
begin
  select max(A) into v_m
  from (select v1 A
        from dual 
        union 
        select v2
        from dual
        union
        select v3
        from dual)
  return v_m;
end;


create or replace function fun_1(v1 number,v2 number,v3 number)
return number is
v_r number;
begin 
  if v1>v2 then
    v_r:=v1;
  else
    v_r:=v2;
  end if;
  if v_r>v3 then
    return v_r;
  else 
    return v3;
  end if;
end;


--制作一个函数,输入一个员工姓名,返回他的工资
create or replace function f2(v_ename varchar2) return number
is
v_sal number;
begin
  select sal into v_sal
  from emp
  where ename=v_ename;
  
  return v_sal;
end;

--制作一个函数,输入员工姓名,返回比他工资高的人数
create or replace function f3(v_ename varchar2) return number
is
v1 number;
begin
  select count(1) into v1
  from emp
  where sal>(select sal
             from emp
             where ename=v_ename);
   return v1;
end;


select f3('SMITH')
from dual


--制作一个函数,输入一个部门编号和一个职位,返回这个部门这个职位的人数
create or replace function f4(v_deptno number,v_job varchar2) return number
is
v1 number;
begin
  select count(1) into v1
  from emp
  where deptno=v_deptno and job=v_job;
   
  return v1;
end;

select f4(30,'SALESMAN')
from dual


--制作一个函数,输入一个部门编号和一个年份,
--返回这个部门这个年份入职的人名
--用逗号隔开
create or replace function f5(v_deptno number,v_year number) return varchar2
is
v_name varchar2(200);
begin
  select wm_concat(ename) into v_name
  from emp
  where deptno=v_deptno and to_char(hiredate,'yyyy')=v_year;
  return v_name;
end;


select f5(20,1981)
from dual


--返回动态游标             --不常用
--制作一个函数,输入一个部门编号,返回这个部门的人名

create or replace function f6(v_deptno number) return sys_refcursor
is
cur_1 sys_refcursor;
v_ename varchar2(20);
begin
  open cur_1 for select ename from emp where deptno=v_deptno;
  loop
    fetch cur_1 into v_ename;
    exit when cur_1%notfound;
    dbms_output.put_line(v_ename);
    end loop;
    
    return cur_1;
    close cur_1;
end;

select f6(10)
from dual

--有out

--输入一个员工编号,输出他的工资,返回他的部门编号
create or replace function f7(v_empno number,v_sal out number) return number
is
v_deptno number;
begin
  select sal,deptno into v_sal,v_deptno
  from emp
  where empno=v_empno;
  
  return v_deptno;
end;

调用     --需要用到匿名块
declare
v1 number;
v2 number;
begin
  v2:=f7(7788,v1);
  dbms_output.put_line(v1||' '||v2);
end;


--有out一般不用函数用存储过程
--自定义函数一般不包含DML
--自定义函数不能包含DDl


--函数小结
                 调用
┌没有参数     SQL调用
├只有in       sql调用
└有out        pl/SQL调用(返回值:=函数名(参..))

--小结
异常┌预定义异常
    ├非预定义异常
    └自定义异常

层层嵌套和子块并列┌变量
                  └异常
自定义函数┌没有参数
          ├只有in
          └有out


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值