SQL语言(四):游标和存储过程

一、游标

    游标的使用可以让用户像操作数据一样操作查询出来的数据集,它提供了一种从集合性质的结果中提取单条记录的手段
游标可以形象的看成一个变动的光标。它实际上是一个指针,它在一段Oracle存放数据查询结果集或数据操作结果集的内存中,可以指向结果集中的任何一条记录。
游标的种类:

  • 静态游标:显式游标和隐式游标
  • REF游标
1、显示游标

    在使用之前必须有着明确的游标声明和定义,定义会关联数据查询语句,通常会返回一行或多行。打开游标后,用户可以利用游标的位置对结果集进行检索,使之返回单一的行记录。关闭游标后不能再对结果集进行任何操作。


使用步骤:

  • 声明游标
  • 打开游标
  • 读取数据
  • 关闭游标

游标属性:

  • %ISOPEN:用于判断游标是否打开。打开返回TRUE
  • %FOUND:用于检测行数据是否有效。有效返回TRUE
  • %NOTFOUND: 于%FOUND 相反,没有提取出数据返回TRUE,否则返回FALSE
  • %ROWCOUNT:累计到当前为止使用FETCH提取数据的行数。
-- 1、声明游标
declare 
cursor cur_emp is
select * from emp where sal>2000;

cursor cur_dept is
select * from dept;

v_emp emp%rowtype;
v_dep dept%rowtype;

begin
  
  delete from emp_temp;
  commit;  

  -- 2、使用游标
  open cur_emp;
  loop

    -- 3、读取数据
    fetch cur_emp into v_emp;

    if cur_emp%found then
      insert into emp_temp(empno,ename,job,mgr,hiredate,sal,comm,deptno) 
      values(v_emp.empno,v_emp.ename,v_emp.job,v_emp.mgr,v_emp.hiredate,v_emp.sal,v_emp.comm,v_emp.deptno);
    else
      dbms_output.put_line('一共插入'||cur_emp%rowcount||'条记录');
      exit;   
    end if;
  end loop ; 
  commit;
  -- 4、关闭游标
  close cur_emp;

  open cur_dept;
  loop
    fetch cur_dept into v_dep;
    if cur_dept%found then
      update emp_temp set dname=v_dep.dname where deptno=v_dep.deptno;
      dbms_output.put_line('部门'||v_dep.deptno||'更新结束,名称'||v_dep.dname||'共'||sql%rowcount||'条记录');
    else
      exit;   
    end if;
  end loop;

  update emp_temp set sal=sal*1.1 where dname='RESEARCH';
  dbms_output.put_line(sql%rowcount||'个员工的工资进行了下调');
  commit;
end

2、隐式游标

当运行SELECT或DML语句时,PL/SQL会打开一个隐式游标

  • 隐式游标由PL/SQL自动管理。
  • 隐式游标的默认名称是SQL。
  • SELECT或DML操作产生隐式游标。
  • 隐式游标的属性始终是最新执行的SQL语句的。



二、存储过程定义

    存储过程就是一段存储在数据库中执行某种功能的程序,其中包含一条或多条SQL语句的PL/SQL代码块。可以在Java、C#编程语言中调用。

存储过程的作用:

  • 简化复杂的操作
  • 增加数据的独立性
  • 提高安全性
  • 提高性能

存储过程调用方法:

  • exec pro_name(参数1..);
  • call pro_name(参数1..);
区别:
1. 但是exec是sqlplus命令,只能在sqlplus中使用;call为SQL命令,没有限制.
2. 存储过程没有参数时,exec可以直接跟过程名(可以省略()),但call则必须带上()

三、无参存储过程

将EMP表中工资最低的3个员工的工资加100元。
create or replace procedure testPro1 is
begin
      
update emp set sal=sal+100 where empno in
( 
       select empno from
       (select empno from emp order by sal )
       where rownum<4
);

commit;
end testPro1;
按照不同的部门将EMP表中员工的信息输出。
create or replace procedure testPro2 is
--查询出emp表中所有的dept
cursor cur_deptno is 
select deptno from emp group by deptno;

v_deptno emp.deptno%type;
v_dname dept.dname%type;
begin
  open cur_deptno;
  loop
    fetch cur_deptno into v_deptno;
    exit when cur_deptno%notfound;
    --deptno->dname
    select dname into v_dname from dept
    where deptno=v_deptno;
    
    if sql%found then
      dbms_output.put_line('-------------'||v_dname||'-------------');
    end if;
    
    --简写游标(注意这里的sql语句后不需要;)输出部门下员工信息
    for v_emp in(
        select * from emp where deptno=v_deptno
        )
      loop
        dbms_output.put_line(v_emp.ename||' '||v_emp.job||' '||v_emp.sal);  
      end loop; 
  end loop;
  close cur_deptno;
end testPro2;

四、带参存储过程

练习:根据输入的部门名称,搜索该部门下员工,并将员工信息打印到屏幕.
create or replace procedure testpro4(p_dname in varchar2) is
v_deptno emp.deptno%type;
begin
  
  select deptno into v_deptno
  from dept
  where dname=p_dname;
  
  if sql%found then
    dbms_output.put_line('---------------'||p_dname||'---------------');
    
    for cur_emp in (
       select * from emp where deptno=v_deptno
      )loop
       dbms_output.put_line(cur_emp.empno||' '||cur_emp.ename||' '||cur_emp.job||' '||cur_emp.sal);     
      end loop;
    
   end if;
exception
  when no_data_found then
    dbms_output.put_line('没有数据');
  when too_many_rows then
    dbms_output.put_line('对应数据不唯一');
end testpro4;
练习:根据输入的部门编号和工资涨幅金额对部门下的员工工资信息调整,并返回修改的记录数。
create or replace procedure testpro6(p_deptno in number, p_num in out number) is
begin
   update emp set sal=sal+p_num where deptno=p_deptno;
   if sql%found then
     p_num:=sql%rowcount;
   end if;
end testpro6;

调用:
declare
v_num number;
begin
  v_num:=300;
  testpro6(10,v_num);
  dbms_output.put_line(v_num);
end;

猜你喜欢

转载自blog.csdn.net/u014231646/article/details/80319049
今日推荐