游标

一、 游标

   位于内存中的 "临时表"。 具体如下:游标是从数据表中提取出来的数据,以 临时表 的形式存放到 内存中,在游标中有一个 数据指针, 在初始状态下指向的是首记录,利用 fetch 语句可以移动该指针,从而对游标中的数据进行各种操作,然后将操作结果写回到数据库中。游标的本质是一个结果集resultset,主要用来临时存储从数据库中提取出来的数据块。

二、 游标的分类

      1. 显式游标:由用户定义,需要的操作:定义游标、打开游标、提取数据、关闭游标,主要用于对查询语句的处理。

      2.显式游标的属性

        (1) %NOTFOUND。表示游标获取数据的时候是否有数据提取出来,没有数据返回TRUE,有数据返回false。经常用来判断游标是否全部循环完毕,如案例1%NOTFOUND为true的时候,说明循环完毕,跳出LOOP循环。

        (2) %FOUND。正好和%NOTFOUND相反,当游标提取数据值时有值,返回TRUE,否则返回FALSE。

        (3) %ISOPEN。用来判断游标是否打开。

        (4) %ROWCOUNT。表示当前游标FETCH INTO获取了多少行的记录值,用来做计数用的。

举例:打印表hu_test中的指定字段

--显示游标
declare 
cursor hu_test_cursor is select owner,object_type,created from hu_test;--定义游标
v_owner hu_test.owner%type;
v_object_type hu_test.object_type%type;
v_created hu_test.created%type;
begin
    open hu_test_cursor;--打开游标
    loop 
        fetch hu_test_cursor into  v_owner,v_object_type,v_created;--提取数据
        dbms_output.put_line('所有者:'||v_owner||' 类型是:'||v_object_type||' 创建时间:'||v_created);
    exit when hu_test_cursor%notfound;
  end loop;
      close hu_test_cursor;--关闭游标
        EXCEPTION
   WHEN OTHERS THEN
     dbms_output.put_line(SQLCODE || ' : ' || SQLERRM);--返回错误消息
      dbms_output.put_line(dbms_utility.format_error_backtrace);--返回错误行
end;    

举例:检验游标是否打开,打开的话显示提取行数

--检验游标是否打开,打开的话显示提取行数
declare 
cursor hu_test_cursor is select owner,object_type,created from hu_test;--定义游标
v_owner hu_test.owner%type;
v_object_type hu_test.object_type%type;
v_created hu_test.created%type;
begin
	open hu_test_cursor;--打开游标
	loop 
		fetch hu_test_cursor into  v_owner,v_object_type,v_created;--提取数据
		dbms_output.put_line('所有者:'||v_owner||' 类型是:'||v_object_type||' 创建时间:'||v_created);
    exit when hu_test_cursor%notfound;
  end loop;
	if(hu_test_cursor%isopen) then DBMS_OUTPUT.PUT_LINE('游标已打开');
	DBMS_OUTPUT.PUT_LINE('读取了'||hu_test_cursor%ROWCOUNT||'行');
	else
		DBMS_OUTPUT.PUT_LINE('游标没有打开');
	end if;	
	  close hu_test_cursor;--关闭游标
		EXCEPTION
   WHEN OTHERS THEN
     dbms_output.put_line(SQLCODE || ' : ' || SQLERRM);--返回错误消息
      dbms_output.put_line(dbms_utility.format_error_backtrace);--返回错误行
end;

  3. 隐式游标:由系统定义并为它创建工作区域,并且隐式的定义打开提取关闭,隐式游标的游标名就是'SQL',属性和显示游标相同,主要用于对单行select语句或dml操作进行处理。

        (1)SQL%ISOPEN:游标是否开启, true:开启,false:关闭

        (2)SQL%FOUND:前一个 fetch 语句是否有值,true:有,false:没有
        (3)SQL%NOTFOUND:与上述相反,常被用于 退出循环,true:没有,false:有, null : 空。注意哦,只有 为 true 时,才退出(当 第一次 fetch 为 null 时,不会退出!)

        (4)SQL%ROWCOUNT:当前成功执行的数据行数(非总记录数

举例:用隐式游标测试插入,更新,删除,查询等

--隐式游标
declare 
v_count number;
begin
	insert into hu_test(owner,object_type,created) values('SYS','test',sysdate);
	IF SQL%FOUND THEN
      dbms_output.put_line('插入成功!');
			commit;
   END IF;
	update hu_test e set e.object_type='CLUSTER1' where e.object_type='CLUSTER';
	IF SQL%FOUND THEN
      dbms_output.put_line('更新成功!');
			commit;
   END IF;
	delete from hu_test e where e.object_id=3; 
	IF SQL%FOUND THEN
      dbms_output.put_line('删除成功!');
			commit;
   END IF;
	select count(*) into v_count from hu_test;
	IF SQL%FOUND THEN
      dbms_output.put_line('总记录为: '||v_count); 
   END IF;
	IF SQL%ISOPEN THEN
      dbms_output.put_line('可手动查看');
   ELSE 
      dbms_output.put_line('无法手动查看');
   END IF;
	EXCEPTION
   WHEN OTHERS THEN
      dbms_output.put_line(SQLCODE || ' : ' || SQLERRM);
      dbms_output.put_line(dbms_utility.format_error_backtrace);
end;

  4.游标FOR循环:隐含的执行了打开提取关闭数据,代码精简很多,syntax:

FOR table_record IN table_cursor LOOP

  STATEMENT;

END LOOP;

举例:游标FOR循环

DECLARE
cursor hu_test_cursor is select owner,object_type,created from hu_test;
BEGIN
  FOR test_cursor IN hu_test_cursor LOOP
    dbms_output.put_line('所有者:'||test_cursor.owner||' 类型是:'||test_cursor.object_type||' 创建时间:'||test_cursor.created);
  END LOOP;
END;

这里游标FOR循环省去了对于取到的数据的变量的命名和赋值,同时如果全部打印则不用写循环条件,代码精简了很多。

如果想让代码更加精简,则可以去掉对游标的声明引入子查询即可,操作如下。

--更简便的for循环
BEGIN
  FOR test_cursor IN (select owner,object_type,created from hu_test) LOOP
    dbms_output.put_line('所有者:'||test_cursor.owner||' 类型是:'||test_cursor.object_type||' 创建时间:'||test_cursor.created);
  END LOOP;
END;

  5.参数游标,动态游标1

举例:输入object_id查询相关数据

--参数游标
declare 
cursor hu_test_cursor(numid number) is	select owner,object_type,created from hu_test e where e.object_id=numid;
BEGIN
  FOR test_cursor IN hu_test_cursor(&numid) LOOP--这里也可以用一个变量来赋值
    dbms_output.put_line('所有者:'||test_cursor.owner||' 类型是:'||test_cursor.object_type||' 创建时间:'||test_cursor.created);
  END LOOP;
END;

  6.参数游标,动态游标2

--动态游标
declare 
v_id hu_test.object_id%type;
v_sql varchar2(2000);
type test_cursor_type is ref cursor;
test_cursor test_cursor_type;
v_owner hu_test.owner%type;
v_object_type hu_test.object_type%type;
v_created hu_test.created%type;
BEGIN
	v_id:=20;
	v_sql:='select owner,object_type,created from hu_test e where e.object_id = :v_id';
	open test_cursor for v_sql using v_id;
	loop
	fetch test_cursor into v_owner,v_object_type,v_created;
  exit when test_cursor%notfound;
    dbms_output.put_line('所有者:'||v_owner||' 类型是:'||v_object_type||' 创建时间:'||v_created);
  END LOOP;
	close test_cursor;
	EXCEPTION
   WHEN OTHERS THEN
      dbms_output.put_line(SQLCODE || ' : ' || SQLERRM);
      dbms_output.put_line(dbms_utility.format_error_backtrace);
END;

  

  

posted @ 2020-04-04 23:22  小胡666  阅读(449)  评论(0编辑  收藏  举报
39
0