Oracle快速入门(游标,抛出自定义异常信息,存储过程)

一、游标:

1、游标的概念:

是用来操作查询结果集的,相当于JDBC中的ResultSet

2、查询结果集(理解游标的作用和概念)

select * from emp;

查询emp表

在这里插入图片描述

3、游标的语法

cursor 游标的名称 is 查询的结果集 

4、游标的开发步骤

(1)声明游标
cursor 游标的名称 is 查询的结果集 
(2)打开游标
open 游标名 
(3)从游标当中取数据fetch 从游标 当中 取一条记录
fetch 游标名 into 变量

判断游标是否取完数据

游标名:%found : 

游标名%notfound :没有找到数据

(4)关闭游标

语法

close 游标名

二、案例

1、不带参数的游标

cursor 游标的名称 is 查询的结果集 
(1)输出员工表中所有的员工姓名和工资(不带参数游标)

结果集(游标):所有员工
声明一个变量,用来记录一行数据 %rowtype

declare
       -- 游标:声明vrows游标 指向emp表的表头
       cursor vrows is select * from emp;     
       -- 声明变量,记录一行数据
       vrow emp%rowtype;--存储的是emp表第一行的数据
begin
     -- 1、打开游标
     open vrows;    
     -- 2、从游标当中提取数据
     -- 循环取数据     
     loop       
        fetch vrows into vrow; -- 通过游标vrows取vrow当中的数据,将vrows 当中的数据放置到vrow
        exit when vrows%notfound;  --当vrows游标找不到的时候退出循环
        dbms_output.put_line('姓名:'|| vrow.ename || ' 工资:' || vrow.sal);   
     end loop;
     --  3、关闭游标
     close vrows;       
end;

在这里插入图片描述
在这里插入图片描述

2、带参数的游标

cursor 游标的名称[(参数名 参数类型)] is 查询的结果集 
(1)输出指定部门下的员工姓名和工资

游标:指定部门的所有员工
声明一个变量记录一行数据

declare

     -- 声明游标
     cursor vrows(dno number) is select * from emp where deptno = dno;
     -- 声明变量
     vrow emp%rowtype;
begin
    -- 1、打开游标,指定10号部门
    open vrows(10);   
    -- 2、循环遍历,取数据
    loop 
       fetch vrows into vrow;  -- 通过游标vrows取vrow当中的数据,将vrows 当中的数据放置到vrow
       exit when vrows%notfound;  --当找不到的时候退出   
       dbms_output.put_line('姓名:'|| vrow.ename || ' 工资:' || vrow.sal);    
    end loop;    
    -- 关闭游标
    close vrows;
  
end;

在这里插入图片描述
在这里插入图片描述

三、系统引用游标

1、系统引用游标语法

(1)声明游标 : 游标名 游标类型 sys_refcursor
(2)打开游标:open 游标名 for 结果集
(3)从游标当中取数据
(4)关闭游标

2、案例演示

select * from emp;
declare 
	-- 声明系统引用游标
	vrows sys_refcursor;
	-- 声明一个变量来用于记录数据
	vrow emp%rowtype;--指向emp表的表头
begin
	--1、打开游标
	open vrows for select * from emp;
	-- 2、取数据
	loop 
		fetch vrows into vrow;--将vrows 当中的数据放置到vrow,vrow会不断循环向下走
		exit when vrows%notfound;
    dbms_output.put_line('姓名:'|| vrow.ename || ' 工资:' || vrow.sal);    
	end loop; 
	close vrows;
end;

在这里插入图片描述

四、扩展内容,,使用for循环遍历游标

for循环遍历游标:不需要声明额外变量,不需要打开游标,不需要关闭游标 if

-- 使用for循环来遍历游标
declare 
   -- 声明一个游标
   cursor vrows is select * from emp;
begin
   for vrow in vrows loop
       dbms_output.put_line('姓名:'|| vrow.ename || ' 工资:' || vrow.sal || vrow.sal || '工作:' || vrow.job);    
   end loop;                         
end;

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

五、例外(意外):程序运行的过程当中发生异常,相当于是Java当中的异常

1、捕获异常的语法

declare 
	-- 声明变量
begin 
	-- 业务逻辑 判断和循环
exception  -- 捕获异常 
	-- 处理异常
	when 异常一 then 
	  ...
	when 异常二 then
	  ...
	when others then
	  ...处理其他异常
end;

2、Oracle当中常见的异常

zero_divide : 除零异常
value_error : 类型转换异常
too_many_rows : 查询出多行记录,但是赋值给了一行记录,rowtype记录一行数据的变量
no_data_fount : 没有找到数据
(1)发生了除零异常
declare
	vi number;
begin
	vi := 8/0;
exception 
	when zero_divide then 
		dbms_output.put_line('发生了除零异常');
	when others then 
		dbms_output.put_line('发生了其他异常');
end;

在这里插入图片描述

(2)其他异常:类型转换异常

给数字类型的变量赋值字符串,发送异常

declare
	vi number;
begin
	vi := 'aaa';
exception 
	when zero_divide then 
		dbms_output.put_line('发生了除零异常');
	when others then 
		dbms_output.put_line('发生了其他异常');
end;

在这里插入图片描述

(3)捕获类型转换异常
declare
	vi number;
begin
	vi := 'aaa';
exception 
	when zero_divide then 
		dbms_output.put_line('发生了除零异常');
  when value_error then
    dbms_output.put_line('发生了类型转换异常');
	when others then 
		dbms_output.put_line('发生了其他异常');
end;

在这里插入图片描述

(4)too_many_rows : 查询出多行记录,但是赋值给了一行记录,rowtype记录一行数据的变量
declare
	vi number;
   -- 记录一行变量
   vrow emp%rowtype;
begin
	 select * into vrow from emp;
exception 
	when zero_divide then 
		dbms_output.put_line('发生了除零异常');
  when value_error then
    dbms_output.put_line('发生了类型转换异常');    
  when too_many_rows then 
    dbms_output.put_line('查询出多行记录,但是赋值给了一行记录,rowtype记录一行数据的变量');
	when others then 
		dbms_output.put_line('发生了其他异常');
end;

在这里插入图片描述

(5) 没有找到数据的异常
declare
	vi number;
  -- 记录一行变量
  vrow emp%rowtype;
begin
	 select * into vrow from emp where empno = 123456; -- 查询数据并赋值给vrow
exception 
	when zero_divide then 
		dbms_output.put_line('发生了除零异常');
  when value_error then
    dbms_output.put_line('发生了类型转换异常');    
  when too_many_rows then 
    dbms_output.put_line('查询出多行记录,但是赋值给了一行记录,rowtype记录一行数据的变量');
	when others then 
		dbms_output.put_line('发生了其他异常' ||  sqlerrm);
end;

在这里插入图片描述
详细的捕获异常

declare
	vi number;
  -- 记录一行变量
  vrow emp%rowtype;
begin
	 select * into vrow from emp where empno = 123456; -- 查询数据并赋值给vrow
exception 
	when zero_divide then 
		dbms_output.put_line('发生了除零异常');
  when value_error then
    dbms_output.put_line('发生了类型转换异常');    
  when too_many_rows then 
    dbms_output.put_line('查询出多行记录,但是赋值给了一行记录,rowtype记录一行数据的变量');    
  when no_data_found then 
    dbms_output.put_line('没有找到数据异常'); 
	when others then 
		dbms_output.put_line('发生了其他异常' ||  sqlerrm);
end;

在这里插入图片描述

六、抛出自定义异常信息

1、语法

异常名 exception;
rasie 异常;

2、查询指定编号的员工,如果没有找到,则抛出自定义的异常。

a、声明一个变量 % rowtype 。
b、查询员工信息信息,保存起来。
c、判断员工信息是否为空。
d、如果是则抛出异常。

(1)抛出其他异常
select * from emp;
-- 查询指定编号的员工,如果没有找到,则抛出自定义的异常
declare
   -- 1、声明一个变量 %rowtype
   vrow emp%rowtype;
   -- 2、声明一个自定义的异常
   no_emp exception;
begin
    -- 3、查询员工信息,保存起来
   select * into vrow from emp where empno = 8888;--抛出异常
   if vrow.sal is null then
     raise no_emp; -- 抛出自定义的异常
   end if;
exception
  -- 捕获异常
    when no_emp then 
      dbms_output.put_line('输出了自定义的异常');
    when others then 
      dbms_output.put_line('输出了其他异常'|| sqlerrm);
end;

在这里插入图片描述

(2)错误演示,抛出指定异常
%found % notfound 

声明一个游标
声明一个变量,记录数据
从游标当中取记录,如果取到了
如果有,则不管
如果没有就抛出自定义异常

declare 
      -- 声明游标vrows是查询表当中的empno = 8888
      cursor vrows is select * from emp where empno = 8888;
      --声明记录型的变量,声明记录型,指向emp表的表头
      vrow emp%rowtype;  
      -- 声明一个自定义异常
      no_emp exception;
begin
      -- 1、打开游标
      open vrows;    
      -- 2、取数据
      fetch vrows into vrow;
      -- 3、判断游标是否有数据
      if vrows%notfound then 
           raise no_emp;--raise申请这个异常
      end if;
      close vrows;
-- 捕获异常
exception 
   when no_emp then
     dbms_output.put_line('发生了自定义的异常');
end;

在这里插入图片描述
在这里插入图片描述

七、存储过程 :实际上是封装在服务器上一段PLSQL代码片段,已经编译好了的代码

1、客户端去调用存储过程,执行效率就会非常高高效

2、语法 :

create [or replace] procedure 存储过程的名称(参数名 in|out 参数类型)is | as 
is | as
 --声明部分
begin 
 -- 业务逻辑
end;

3、给指定员工涨薪,并打印涨薪前和涨薪后的工资

参数:in 员工编号
参数:in 涨多少

声明一个变量:存储涨工资前的工资

查询出当前工资是多少

打印涨薪前的工资

更新工资

打印涨薪后的工资

create or replace procedure proc_updatesal(vempno in number,vnum in number)
is 
	--声明变量,记录当前工资
	vsal number;
begin
	-- 查询当前工资
	select sal into vsal from emp where empno = vempno;
	--输出涨薪前的工资
	dbms_output.put_line('涨薪前:' || vsal);
	--更新工资
	update emp set sal = vsal + vnum where empno = vempno;
	--输出涨薪后的工资
	dbms_ouput.put_line('涨薪后:' || (vsal+vnum));
	--提交事务
	commit;
end;

在这里插入图片描述

-- 方式1
call proc_updatesal(7788,10);

在这里插入图片描述

-- 方式2  用的最多的一种方式
declare 
begin
   proc_updatesal(7788,-100);
end;

在这里插入图片描述

八、存储函数:实际上是一段封装在Oracle服务器中的一段PLSQL代码片段,它是已经编译好了的代码片段

1、语法

create {
   
   or replace} function 存储函数的名称(参数名 in|out 参数类型,参数名 in|out 参数类型) 
is | as

begin

end;

2、存储过程和函数的区别;

(1)他们本质上没有区别。
(2)函数存在的意义是给过程调用的 存储过程里面调用存储函数
(3)函数可以在sql语句里面直接调用。
(4)存储过程能实现的,存储函数也能实现,存储函数能实现的,存储过程也能实现
默认就是in。

3、相关案例

(1)查询指定员工的年薪

参数:员工的编号
返回:年薪

a、创建存储函数(返回值的方式得到对应的值)
create or replace function func_getsal(vempno number) return number
is
	-- 声明变量.保存年薪
	vtotalsal number;
begin
	select sal*12 + nvl(comm,0) into vtotalsal from emp where empno = vempno;
	return vtotalsal;
end;

在这里插入图片描述

b、调用存储函数:查询某个员工编号对应的年薪

调用上面创建的函数,查询7788员工编号对应的员工信息

declare 
	vsal number;
begin
	vsal := func_getsal(7788);
	dbms_output.put_line(vsal);
end;

在这里插入图片描述

(2)查询员工的姓名,和他的年薪
select ename,func_getsal(empno) from emp;

在这里插入图片描述

(3)查询指定员工的年薪–使用存储过程来实现(传入参数,将值存储到参数当中)

参数:是员工编号
输出:年薪

create or replace procedure proc_gettotalsal(vempno in number,vtotalsal out number)
is

begin
	select sal*12 + nvl(comm,0) into vtotalsal from emp where empno = vempno;
end;

在这里插入图片描述

declare
 vtotal number;--声明变量调用函数
begin
  proc_gettotalsal(7788,vtotal);-- 调用函数查询年薪和工资
  dbms_output.put_line('年薪:'||vtotal);输出年薪
end;

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_44757034/article/details/108555127