文档章节

oracle 游标基础

陈爱茹cx1992
 陈爱茹cx1992
发布于 2016/07/26 17:35
字数 2190
阅读 7
收藏 1
一、显示游标
  1、声明游标
    (1)声明一个游标用来查询表students中的所有学生姓名
    
    declare cursor cu_student_name is
            select student_name from students;
    声明一个游标的时候一般还应当声明一个相应的变量,专门用来获取游标中的数据
    
    (2)声明游标和游标对应的局部变量
        declare cursor cu_student_name is
            select student_name from students;
            student_name varchar2(32);
        游标中有多列,通常为每列声明一个变量
    (3)在游标内部声明变量
        declare cursor cu_student_id_name is
            select student_id,student_name from students;
            student_id varchar2;
            student_name varchar2(32);
    (4)使用列类型声明变量
        declare cursor cu_student_id_name is
            select student_id,student_name from students;
            student_id students.student_id%type;
            student_name students.student_name%type;
    (5)声明行类型变量
        declare cursor cu_student is
            select * from students;
            student students%rowtype;
    (6)声明带参数的游标
        declare cursor cu_student(minAge in number,maxAge in number) is
            select * from students where student_age >=minAge and student_age <=maxAge;
            student students%rowtype;
            
  2、使用游标
    (1)使用变量获取游标信息
       declare cursor cu_student_id_name is
           select student_id,student_name from students;
           
           student_id students.student_id%type;
           student_name students.student_name%type;
           
           begin
             open cu_student_id_name;
             fetch cu_student_id_name into student_id,student_name;
             
             while cu_student_id_name %found loop
               dbms_output.put_line(student_id || ':' || student_name);
               fetch cu_student_id_name into student_id,student_name;
             end loop;
             
             close cu_student_id_name;
           end;
       说明: open cu_student_id_name 用于打开游标
             fetch cu_student_id_name into student_id,student_name:从游标中获取数据
             while cu_student_id_name %found loop 用于循环处理
             cu_student_id_name%found返回一个布尔值,即游标的当前位置能否获得记录,
             每次对游标使用fetch动作时都会更新%found 属性;
             dbms_output.put_line(student_id || ':' || student_name);用于输出当前变量
             student_id和student_name的信息;
             fetch cu_student_id_name into student_id,student_name;将游标位置向下移动,
             并获取移动后的记录
     (2)利用行类型获取游标信息
        declare cursor cu_student is
           select * from students;
           student students%rowtype;
           begin
             open cu_student;
             fetch cu_student into student;
             
             while cu_student%found loop
               dbms_output.put_line(student.student_id || '-' || student.student_name);
               fetch cu_student into student;
             end loop;
             close cu_student;
           end;
     (3)使用带有参数的参数
        declare cursor cu_student(minAge in number,maxAge in number) is
          select * from students where student_age >= minAge and student_age <=maxAge;
          student students%rowtype;
          
          begin
            open cu_student(19,20);
            fetch cu_student into student;
            
            while cu_student%found loop
              dbms_output.put_line(student.student_name || ':' || student.student_age || '岁');
              fetch cu_student into student;
            end loop;
         end;
二、隐式游标
	隐式 游标有两种:使用oracle预定义的名为sql 的隐式游标 和使用 cursor for loop 进行循环的隐式游标。
   1、 sql 的隐式游标。 oracle为pl/sql的会话都定义了一个名为 sql的游标变量 。可以在plsql中直接调用该变量
      (1)在plsql中直接调用游标变量sql
          begin
            if sql%rowcount>0 then
              dbms_output.put_line('sql 游标变量的 rowcount 属性大于 0');
            end if;
          end;
          
          说明 : if sql%rowcount >0 then 用于获得游标变量sql的rowcount属性,即游标的行数。
          根据游标变量是否能够抓取记录进行条件判断,并输出响应的提示
      (2)oravle 自动更新游标变量
          begin
            update students set student_age = student_age - 1;
            dbms_output.put_line('共更新了' || sql%rowcount || '条记录');
          end;
  2、sql隐式游标
    -- 尝试控制sql游标变量(错误示例)
    declare
      student students%rowtype;
      begin
        update students set student_age = student_age;
        fetch sql into student;
        while sql%found loop
              dbms_output.put_line(student.student_id || ':' || student.student_name
              || ' ' || student.student.student_age
              );
        fetch sql into student;
        end loop;
       end;
    游标变量sql并不能使用fetch命令显示操作。
    sql隐式变量只能用于更新删除等操作之后的属性信息获取
  3、cursor for 游标
    利用该游标可以像使用普通循环语句一样来处理select语句所获得的每一天记录
    (1)演示 cursor for 游标的使用
          begin
            for student in (select * from students) loop
              dbms_output.put_line(
                student.student_id || ':' || student.student_name || '--'
                || student.student_age || '岁'
              );
            end loop;
          end;
          代码说明
          for student in (select * from students) loop 用于创建循环,
          student 为循环中的临时变量 像for(i=0;i<count;i++)中的i一样;
          select * from students 用于获得要处理的结果集;
           dbms_output.put_line(); 用于输出学生的基本信息,
          student.student_id 用户获得student变量的student_id的属性
        
     (2)需求:
        父表c_louyu,子表c_room 关联字段c_louyu中的lh和c_room的louhao
        把子表中的louhao换成对应的父表对应的id
        begin 
            for p_louyu in (select * from c_louyu) loop
              dbms_output.put_line(
               'update c_room set louhao = ''' || p_louyu.id || ''' where louhao = ''' || p_louyu.lh || ''';'
              );
            end loop;
        end;

        create table C_LOUYU
        (
          id  CHAR(32),
          lh  VARCHAR2(20),
          glz VARCHAR2(32),
          mc  VARCHAR2(50),
          bz  VARCHAR2(50)
        );
        create table C_ROOM
        (
          id        CHAR(32),
          louhao    VARCHAR2(32),
          fanghao   VARCHAR2(32),
          bumen     VARCHAR2(32),
          shuliang  VARCHAR2(32),
          louceng   VARCHAR2(32),
          dianhua   VARCHAR2(32),
          bukeyong  VARCHAR2(32),
          chaoxiang VARCHAR2(32)
        );
      
   游标属性
   常用 found、not found、rowcount、isopen
   利用4中属性坚实游标状态
      declare
        cursor students is select * from students;
        student students%rowtype;
        begin
          if students%isopen then
             dbms_output.put_line('声明游标之后,游标已经打开');
          else
             dbms_output.put_line('声明游标之后,游标尚未打开');
          end if;
          
          open students;
          if students%isopen then
             dbms_output.put_line('执行open之后,游标已经打开');
          else
             dbms_output.put_line('执行open之后,游标尚未打开');
          end if;
          
          fetch students into student;
             dbms_output.put_line('第一次执行fetch之后,游标rowcount 属性值为' || students%rowcount);
          if students%found then
             dbms_output.put_line('第一次执行fetch之后,游标 found 属性值为 :true');
          else
             dbms_output.put_line('第一次执行fetch之后,游标 notfound 属性值为 :true');
          end if;
          dbms_output.put_line('-------------------------------------');
          
          loop
            if students%found then
              dbms_output.put_line('循环执行。。游标的rowcount 属性值为:' || students%rowcount);
              fetch students into student;
            else
              dbms_output.put_line('游标的 found 属性为 ' || students%found);
              dbms_output.put_line('完毕。。游标的rowcount 属性值为:' || students%rowcount);
              exit;
            end if;
          end loop;
          dbms_output.put_line('-------------------------------------');
          close students;
          if students%isopen then
            dbms_output.put_line('执行close 命令之后,游标任然打开');
          else
            dbms_output.put_line('执行close 命令之后,游标关闭');
          end if;
        end;

三、动态游标
	1、强类型动态游标
		 强类型动态游标:当游标声明时,虽然未设定其查询语句,但是已经指定了游标的返回类型
		 游标返回类型可以是oracle内置类型,也可以是自定义类型。
		 
		 声明一个强类型游标首先自定义一个 ref cursor 的游标类型 , 然后利用该自定义类型,声明一个游标
		 eg:先需要一个打印学生信息的存储过程,用户可以向存储过程传递一个年龄参数,
		 如果传入的年龄小于等于0 则打印所有学生的信息,如果传入的参数大于0 ,则打印年龄与参数相同的学生信息
		 
		 eg; 演示如何利用强类型动态游标打印学生信息
		   create or replace procedure printStudents(in_age in number) as
			 begin
			   declare
				  type student_type is record(
					   id varchar2(32),
					   name varchar2(32),
					   age number
				  );
				  type students_type is ref cursor
					   return student_type;
				  
				  v_students students_type;
				  v_student student_type;
				
				  begin
					if in_age <=0 then
					  open v_students for
						   select * from students;
					else
					  open v_students for
						   select * from students where student_age = in_age;
					end if;
					
					fetch v_students into v_student;
					
					  while v_students%found loop
						dbms_output.put_line(v_student.id || ':' 
											|| v_student.name || ':'
											|| v_student.age || ':'
						);
						
						fetch v_students into v_student;
					  end loop;
					close v_students;
				   end;
			 end printStudents;
			 
		   说明:
		   declare type student_type is record(id varchar2(32),name varchar2(32),age number);
		   用于声明自定义类型student_type ,该类型的基类是一个record 类型,他包含3个属性,id,name.age。
		   
		   type students_type is ref cursor return student_type;用于声明自定义类型。
		   ref cursor 表明该自定义游标是一个动态游标,
		   return student_type :该动态游标是强类型动态游标,返回结果集的类型是 student_type,
		   注:student_type是结果集类型,students_type是游标类型。
		   因为students_type 引用到了student_type ,所以首先声明student_type 然后声明students_type
		   二者顺序不可颠倒;
		   v_students students_type 用于声明变量 v_students, 该变量是一个动态游标;
		   v_student student_type 用于声明变量 v_student 该变量是一个 record 类型;
		   if in_age <=0 用于判断存储过程的传入参数是否为 0 ;
		   open v_students for select * from students where student_age = in_age; 
		   表示 当传入的年龄参数大于0 时 按照实际年龄进行查询;
		   fetch v_students into v_student; 用于获取游标中的记录 ,并存储在变量 v_student 中;
		   while v_students%found loop 用于创建循环,
		   该循环执行的条件 可以从游标 v_students 中获取记录,
		   dbms_output.put_line(···); 利用变量v_student输出学生信息。
		   
		   测试
			 begin printStudents(19);
			 end;
			 
	2、弱类型动态游标
	 弱类型动态游标:在声明游标时不使用 return 关键字指定游标的返回类型,那么在以后的程序中,
	 可以对其使用不同的返回类型。例如,对于学生表,用户可能只希望获得学生姓名或学生的年龄,
	 则可以创建一个存储过程,向存储过程传递一个参数,该参数标识用户希望获得的数据。
	 此时,可以利用弱类型游标来实现此功能。
	 
	 (1) 使用弱类型游标
		 create or replace procedure printStudentsByFlag(in_flag in varchar2) as
				begin
				  declare
				   type name_type is record (
						id varchar2(32),
						name varchar2(32)
				   );
				   type age_type is record (
						id varchar2(32),
						age number
				   );
				   type students_type is ref cursor;
				   
				   v_name name_type;
				   v_age age_type;
				   v_students students_type;
				   
				 begin
				   if upper (in_flag) = 'NAME' then
					 open v_students for
						  select student_id,student_name from students;
						  
					 fetch v_students into v_name;
					 
					 while v_students%found loop
					   dbms_output.put_line(v_name.id || '号 学生的姓名是:' || v_name.name);
					   fetch v_students into v_name;
					 end loop;
					elsif upper(in_flag) ='AGE' then
					  open v_students for
						   select student_id,student_age from students;
					  fetch v_students into v_age;
					  
					  while v_students%found loop
						dbms_output.put_line(v_age.id || '号 学生的年龄是:' || v_age.age);
						fetch v_students into v_age;
					  end loop;
					end if;
					
					if v_students%isopen then
					  close v_students;
					end if;
				  end;
				end printStudentsByFlag;
			测试
			begin
			  printStudentsByFlag('age');
			end;
	 (2) cursor for 游标的使用
		 
		 begin
		   for student in (select * from students where student_age >= 18 order by student_age desc)
			   loop
			   dbms_output.put_line(
					   student.student_name || ':' || student.student_age || '岁'
			   );
			   end loop;
		 end;

本文转载自:http://blog.csdn.net/ruru7989/article/details/12689803

共有 人打赏支持
陈爱茹cx1992
粉丝 0
博文 59
码字总数 0
作品 0
济南
程序员
oracle常见基础知识

oracle使用的脚本语言称为什么? PL-SQL oracle中游标的分类? oracle中游标分为两类:显示游标和隐式游标 oracle中function与procedure的区别? (1) function一定要有返回值,但procedure不...

Gong_Chen
2016/04/04
84
0
温故而知新之Oracle 父子游标

当两个sql文本相同,而其他环境不同,这两个游标不能共享执行计划。它们都有各自的执行计划存在缓存库中。这两个游标就是子游标,oracle还会建立一个父游标,父游标没有执行计划,只是文本相...

lych528
06/29
0
0
Winform开发框架之存储过程的支持--存储过程的实现和演化提炼(1)

在我前面很多篇关于框架设计和介绍的文章里面,大多数都是利用框架提供的基础性API进行各种的操作,包括增删改查、分页等各种实现和其衍生的实现,而这些实现绝大多数是基于SQL的标准操作实现...

walb呀
2017/12/04
0
0
每周一书《Oracle 12 c PL(SQL)程序设计终极指南》

本周为大家送出的书是《Oracle 12 c PL(SQL)程序设计终极指南》,此书由机械工业出版社出版, 孙风栋,王澜,郭晓惠 著。 内容简介: 《Oracle 12c PL/SQL程序设计终极指南》志在打造PL/SQL领...

zting科技
2017/12/11
0
0
python cx_Oracle基础使用方法

问题 使用python操作oracle数据库,获取表的某几个字段作为变量值使用。 使用+的方法需要对格式进行控制,通过流获取这几个字段值不简洁。(优点是能够使用的方法直接访问sql文件,不需要考虑...

莫显辉
2017/11/15
0
0

没有更多内容

加载失败,请刷新页面

加载更多

【大福利】极客时间专栏返现二维码大汇总

我已经购买了如下专栏,大家通过我的二维码你可以获得一定额度的返现! 然后,再给大家来个福利,只要你通过我的二维码购买,并且关注了【飞鱼说编程】公众号,可以加我微信或者私聊我,我再...

飞鱼说编程
今天
1
0
Spring5对比Spring3.2源码之容器的基本实现

最近看了《Spring源码深度解析》,该书是基于Spring3.2版本的,其中关于第二章容器的基本实现部分,目前spring5的实现方式已有较大改变。 Spring3.2的实现: public void testSimpleLoad(){...

Ilike_Java
今天
1
0
【王阳明心学语录】-001

1.“破山中贼易,破心中贼难。” 2.“夫万事万物之理不外于吾心。” 3.“心即理也。”“心外无理,心外无物,心外无事。” 4.“人心之得其正者即道心;道心之失其正者即人心。” 5.“无...

卯金刀GG
今天
2
0
OSChina 周三乱弹 —— 我们无法成为野兽

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @ _刚刚好: 霸王洗发水这波很骚 手机党少年们想听歌,请使劲儿戳(这里) hahahahahahh @嘻酱:居然忘了喝水。 让你喝可乐的话, 你准忘不了...

小小编辑
今天
9
0
vm GC 日志 配置及查看

-XX:+PrintGCDetails 打印 gc 日志 -XX:+PrintTenuringDistribution 监控晋升分布 -XX:+PrintGCTimeStamps 包含时间戳 -XX:+printGCDateStamps 包含时间 -Xloggc:<filename> 可以将数据保存为......

Canaan_
昨天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部