Oracle 游标

--游标 : 是oracle系统在内存中开辟的一个工作区,可以存放select查询结果

   游标是 SQL 的一个内存工作区,由系统或用户以变量的形式定义。游标的作用就是

用于临时存储从数据库中提取的数据块。在某些情况下,需要把数据从存放在磁盘的表

中调到计算机内存中进行处理,最后将处理结果显示出来或最终写回数据库。这样数据处理

的速度才会提高,否则频繁的磁盘数据交换会降低效率。



游标有两种类型:显式游标和隐式游标。

隐式游标:是指非PL/SQL程序中定义的、而且是在PL/SQL中使用UPDATE/DELETE语句时,Oracle系统自动

分配的游标 

如:(sql%rowcount)。在前述程序中用到的 SELECT…INTO…查询语句,一次只能从数据库中提取一行

数据,对于这

种形式的查询和 DML 操作,系统都会使用一个隐式游标。


显示游标 ::在PL/SQL程序中定义的、用于查询的游标称作显示游标  如:要提取多行数据,就要由程

序员定义一个

显式游标,并通过与游标有关的语句进行处理。显式游标对应一个返回结果为多行多列的 SELECT 语句

。游标一旦打

开,数据就从数据库中传送到游标变量中,然后应用程序再从游标变量中分解出需要的数据,并进行处

理。





--1隐式的游标(sql游标):不需要open,fetch close等操作。一次只能从数据库中提取一行数据。

删除部门号为20的记录,输出有多少行被删除
declare 
   deptno_1 emp.deptno%type:=20

begin
   delete from emp where deptno=deptno_1;
   dbms_output.putline(sql%rowcount||'行被删除');--sql%rowcount非程序定义的
end;



---2显式的游标:(用于查询语句中)open打开游标 fetch提取数据 ,close 关闭游标操作

---2.1打印出dept表中的所有人的部门号和部门名(标量变量 dept.deptno%type)
declore
	cursor dept_cursor is
	select deptno,dname from dept;
	v_deptno dept.deptno%type;
	v_dname dept.dname%type;
begin
    open dept_cursor
    	loop
    	fetch dept_cur into v_deptno,v_dname;--循环着一条一条的提取
    	exit when deot_cur%notfound;--当游标不再有数据时退出
    	dbms_output.putline(v_deptno);
	dbms_output.putline(v_dname);----一条一条的循环输出
        end loop;
    close dept_cur;
end;---在触发器和存储过程中要结束触发器和存储过程 游标中不需要,但要关闭游标





-----2.2打印出dept表中的所有人的部门号和部门名(记录变量%rowtype)
declare
	dept_record dept%rowtype;
      cursor dept_cursor2 is
	select*from dept;--这里必须要查询全部,因为后期把游标的数据放入dept_record中,

dept_record中含有 一行中的全部列
begin
     open dept_cursor2;
	loop
	exit when dept_cur%notfound or dept_cursor%rowcount>3;------dept_cursor%rowcount>3 

rowcount 从0开始计数为输出前三行
	fetch dept_cur2 into dept_record;
	dbms_output.putline(dept_record.deptno);
	dbms_output.putline(dept_record.dname);
        end loop;
     close dept_cursor;
end;




-----2.3打印出dept表中的所有人的部门号和部门名(集合变量 
1.type dept_table_type is table of(数据类型) dept_cur3%rowtYPE INDEX by binary_integer   
2.type dept_table_type is table of number(33)
3.TYPE empno_table_type IS TABLE OF NUMBER INDEX BY BINARY_INTEGER。。。。。。。还有其他形

式)

-----ql%rowcount中的sql是oracle的内部游标,rowcount的意思是之前的dmlsql语句影响的多少行数据

。如--果是-----delete操作rowcount就是delete的数据,如果是insert,就是插入的数量...... 

declare 
   	cursor dept_cur3 is
	  select*from dept;
    	type dept_table_type is table of dept_cur3%rowtype index by binary_integer -----定

义的集合类型为dept_cur3一行的数据类型 下标为整型,后面需定义下标值
begin
      open dept_cur3
       	loop
	index:=dept_cursor%rowcount+1;---循环一次时下标为一,第二次时下标为二。。。。。。。
	fetch dept_cur3 into type_dept_table;
	exit when dept_cur3%notfound ;
	dbms_output.putline(type_table_type(index).deptno);
	dbms_output.putline(type_table_type(index).dname);
        end loop;
     close dept_cur3;
end;



--------3 带参数的游标


DECLARE
   --定义一个游标
   CURSOR dept_cursor(v_deptno NUMBER DEFAULT 30) IS
          SELECT deptno,dname,loc FROM dept WHERE deptno<v_deptno;
   
   dept_record dept%ROWTYPE;   
   
   
 BEGIN  
   OPEN dept_cursor;
  --- OPEN dept_cursor(v_deptno=>&deptno);------若参数中没有default 30(默认为30),则用此

句sql语句
   LOOP
     --提取数据
     FETCH dept_cursor INTO dept_record;
     EXIT WHEN dept_cursor%NOTFOUND OR dept_cursor%ROWCOUNT>3;
     dbms_output.put_line('部门号:'||dept_record.deptno);
     dbms_output.put_line('部门名称:'||dept_record.dname);
     dbms_output.put_line('部门地址:'||dept_record.loc);  
     dbms_output.put_line('==================');
   END LOOP;
   --关闭游标
   CLOSE dept_cursor;
 END;

----带不带参数没有太大的区别,带参数则是在where语句有用到。若参数没有默认大小则在打开时进行

从键盘输入个-----。如 OPEN dept_cursor(v_deptno=>&deptno);



-------4使用for循环的游标,for循环会自动执行open, fetch,close

declare
    cursor dept_cur4 is
	select deptno,dname,loc from dept;
begin
    for dept_record in dept_cur4 loop
       dbms_output.put_line('部门号:'||dept_record.deptno);
       dbms_output.put_line('部门名称:'||dept_record.dname);
       dbms_output.put_line('部门地址:'||dept_record.loc);  
       dbms_output.put_line('==================');
    end loop;
end;


-----4.2 for循环的简化形式

declare

begin
    for dept_record in (select deptno,dname,locfrom dept) loop
       dbms_output.put_line('部门号:'||dept_record.deptno);
       dbms_output.put_line('部门名称:'||dept_record.dname);
       dbms_output.put_line('部门地址:'||dept_record.loc);  
       dbms_output.put_line('==================');
    end loop;
end;

	
----5 使用游标修改数据
------修改指定部门的员工的最低工资为1500
declare
	v_deptmo deptno%type:=&deptno;
	cursor emp_cursor is
		select empno,sal from emp where deptno=v_deptno for update nowait;
begin
        for emp_record in emp_cursor loop
	if emp_record.sal<1500 then
	dbms_output.line('职工号'||emp_record.deptno);
	dbms_out.putline('工资'||emp_record.sal);
     	update emp set sal=1500 where current of emp_cursor;-----current of emp_cursor为获

取游标当前行的值。
        end if;
	end loop;
        commit;
end;




for update 与for update nowait区别
for update :使用的话(使用的进程为其加锁),则会使后面的进程等待,直到本进程结束。
for update nowait:使用的话(使用的进程为其加锁),则不会使后面的进程等待,直接报错误信息。

sql_1:select 1 from dual for update;

sql_2:select 1 from dual for update;

sql_3:select 1 from dual for update nowait;

执行sql_1,不提交,表dual被锁?

分支1):执行sql_2,sql_2被阻塞,等待sql_1提交

分支2):执行sql_3,因为有nowait,所以立即返回错误信息 "ORA-00054 : 资源正忙,但指定以NOWAIT方式

获取资源"
 

总结:nowait关键字,通知Oracle该sql语句采用非阻塞的方式修改或删除数据,如果发现涉及到的数据被

占有(被锁),则立即通知Oracle该资源被占用,返回错误信息


--定义一个游标
cursor dept_cursor  is
	select deptno,dname,from dept

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值