Oracle_04---游标,存储过程、存储函数、触发器、Java调用存储

游标

游标(光标): 是用来操作查询结果集,相当于是JDBC中ResultSet
   
   语法: cursor 游标名[(参数名 参数类型)] is 查询结果集
   
   开发步骤:
       1. 声明游标 cursor vrows is
       2. 打开游标 open 游标名
       3. 从游标中取数据  fetch 游标名 into 变量
                     游标名%found :找到数据
                     游标名%notfound : 没有找到数据 
       4. 关闭游标       close 游标名
       
  系统引用游标
       1. 声明游标 : 游标名 sys_refcursor
       2. 打开游标: open 游标名 for 结果集
       3. 从游标中取数据
       4. 关闭游标
            
 for循环遍历游标:
       不需要声明额外变量
       不需要打开游标
       不需要关闭游标    

不带参数游标


--输出员工表中所有的员工姓名和工资(不带参数游标)

   游标:所有员工
   声明一个变量,用来记录一行数据  %rowtype
*/
declare
   --声明游标(范围)
   cursor vrows is select * from emp;
   --声明变量,记录一行数据
   vrow emp%rowtype;
begin
   --1.打开游标  
   open vrows;
   --2.从游标提取数据
   --循环取数据
   loop
       fetch vrows into vrow;  --循环从游标中取数据到变量中
       exit when vrows%notfound;  --未取到数据时,退出循环
       dbms_output.put_line('姓名:'||vrow.ename ||' 工资: ' || vrow.sal);
   end loop;
   --3.关闭游标
   close vrows;
end;

带参数游标

--输出指定部门下的员工姓名和工资
/*
   游标: 指定部门的所有员工
   声明一个变量记录一行数据
*/
declare
   --声明游标
   cursor vrows(dno number) is select * from emp where deptno = dno;   --select * from emp where deptno = dno  取出deptno(部门)编号为dno的所有员工
   --声明变量
   vrow emp%rowtype;
begin
  --1.打开游标 , 指定10号部门
  open vrows(10);
  --2. 循环遍历,取数据
  loop
     fetch vrows into vrow;
     exit when vrows%notfound;    
      dbms_output.put_line('姓名:'||vrow.ename ||' 工资: ' || vrow.sal);
  end loop;
  close vrows;
end;

系统引用游标

--输出员工表中所有的员工姓名和工资
declare
  --声明系统引用游标
  vrows sys_refcursor;
  --声明一个变量
  vrow emp%rowtype;
begin
  --1.打开游标
  open vrows for select * from emp;
  --2.取数据
  loop
    fetch vrows into vrow;
    exit when vrows%notfound;
     dbms_output.put_line('姓名:'||vrow.ename ||' 工资: ' || vrow.sal);
  end loop;
  close vrows;
end;

使用for循环遍历游标

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

例外

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

   declare
       --声明变量
   begin
       --业务逻辑
   exception
       --处理异常
       when 异常1 then
         ...
       when 异常2 then
         ...
       when others then
         ...处理其它异常
   end;
   
   zero_divide : 除零异常
   value_error : 类型转换异常
   too_many_rows : 查询出多行记录,但是赋值给了rowtype记录一行数据变量
   no_data_found : 没有找到数据
       
   
   自定义异常:
       异常名  exception;  需要声明异常名
       raise 异常名          
declare
   vi number;
   vrow emp%rowtype;
begin
   --vi := 8/0;  
   --vi := 'aaa';
   --select * into vrow from emp;
   select * into vrow from emp where empno=1234567;
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;

存储过程

存储过程: 实际上是封装在服务器上一段PLSQL代码片断,已经编译好了的代码
          1.客户端取调用存储过程,执行效率就会非常高效
     语法:
          create [or replace] procedure 存储过程的名称(参数名 in|out 参数类型,参数名 in|out 参数类型)
          is | as
           --声明部分
          begin
           --业务逻辑 
          end; 
		  
调用存储过程的两种方式
--方式1
call proc_updatesal();

--方式2 
declare
begin
  proc_updatesal();
end;
--给指定员工涨薪,并打印涨薪前和涨薪后的工资

   参数 : 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_output.put_line('涨薪后:'||(vsal+vnum));
 --提交
 commit;
end;

存储函数

存储函数: 实际上是一段封装是Oracle服务器中的一段PLSQL代码片断,它是已经编译好了的代码片段
    
    语法: 
         create [or replace] function 存储函数的名称(参数名 in|out 参数类型,参数名 in|out 参数类型) return 参数类型
         is | as
         
         begin
           
         end;
    存储过程和函数的区别:
         1.它们本质上没有区别
         2.函数存在的意义是给过程调用   存储过程里面调用存储函数
         3.函数可以在sql语句里面直接调用
         4.存储过程能实现的,存储函数也能实现,存储函数能实现的,过程也能实现
--查询指定员工的年薪

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

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;

--调用存储函数
declare
  vsal number;
begin
  vsal := func_getsal(7788);
  dbms_output.put_line(vsal);
end;

触发器

触发器: 当用户执行了 insert | update | delete 这些操作之后, 可以触发一系列其它的动作/业务逻辑
       作用 : 
            在动作执行之前或者之后,触发业务处理逻辑
            插入数据,做一些校验
        
   语法:
       create [or replace] trigger 触发器的名称
       before | after
       insert | update | delete 
       on 表名
       [for each row]
       declare
       
       begin
         
       end;
       
   触发器的分类:
       语句级触发器:   不管影响多少行, 都只会执行一次
       
       行级触发器:     影响多少行,就触发多少次
              :old  代表旧的记录, 更新前的记录
              :new  代表的是新的记录
--新员工入职之后,输出一句话: 欢迎加入黑马程序员
create or replace trigger tri_test1
after
insert
on emp
declare

begin
  dbms_output.put_line('欢迎加入黑马程序员');
end;

JAVA调用存储过程

   JDBC的开发步骤:
      1.导入驱动包
      2.注册驱动
      3.获取连接
      4.获取执行SQL的statement
      5.封装参数
      6.执行SQL
      7.获取结果
      8.释放资源   


public class TestProcedure {

	@Test
	/*
	 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;
	 * */
	public void test1() throws Exception{
		//注册驱动
		Class.forName("oracle.jdbc.driver.OracleDriver");
		//2.获取连接
		String url = "jdbc:oracle:thin:@192.168.80.100:1521:orcl";
		String username = "dakang";
		String password = "dakang";
		Connection conn = DriverManager.getConnection(url, username, password);
		//3.获取执行SQL的statement.这是一个固定格式  proc_gettotalsal是一个存储函数
		String sql = "{call proc_gettotalsal(?,?)}";
		CallableStatement state = conn.prepareCall(sql);
		//设置输入参数
		state.setInt(1, 7788);//设置员工编号
		//注册输出参数类型
		state.registerOutParameter(2, OracleTypes.NUMBER);
		
		//4.执行statement
		state.execute();
		
		//5.获取执行结果
		int totalsal = state.getInt(2);
		
		//输出结果
		System.out.println("工资:"+ totalsal);
		
		//6.释放资源
		state.close();
		conn.close();
	}
	
	//调用存储函数
	/*
	 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; 
	 */
	@Test
	public void test2() throws Exception{
		//注册驱动
		Class.forName("oracle.jdbc.driver.OracleDriver");
		//2.获取连接
		String url = "jdbc:oracle:thin:@192.168.80.100:1521:orcl";
		String username = "dakang";
		String password = "dakang";
		Connection conn = DriverManager.getConnection(url, username,password);
		//3.获取执行SQL的statement
		String sql = " {?= call func_getsal(?)}";
		CallableStatement state = conn.prepareCall(sql);
		//4.封装参数
		//注册返回类型参数
		state.registerOutParameter(1, OracleTypes.NUMBER);
		//设置第二个参数
		state.setInt(2, 7788);
		//5.执行SQL
		state.execute();		
		//6.获取结果
		int totalsal = state.getInt(1);
		System.out.println("年薪 :  ====" +totalsal);		
		//7.释放资源
		state.close();
		conn.close();
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值