【PL/SQL】 使用游标

一、游标分类

1.隐式游标

①对于SELECT …INTO…语句,一次只能从数据库中获取到一条数据,对于这种类型的DML SQL语句,就是隐式CURSOR

②Select/Update/Insert/Delete操作

2.显式游标:由程序员定义和管理

①对于从数据库中提取多行数据,就需要使用显式CURSOR

②定义游标——CURSOR [CURSOR NAME] IS

③打开游标——OPEN [CURSOR NAME]

④操作数据——FETCH [CURSOR NAME]

⑤关闭游标——CLOSE [CURSOR NAME]

                                   

二、显式游标

·专门用于处理SELECT语句返回的多行数据

·定义游标

①使用显式游标前必须先定义游标

②执行相应的SELECT语句

③语法:

CURSOR cursor_name IS select_statement;

 

·打开游标

①打开显式游标时会执行相应的SQL语句

②将执行结果存放在结果集中

③语法:

OPEN cursor_name;

 

·提取数据

①使用FETCH子句一次提取一条或多条记录

②variable用于接收游标数据的变量

③语法:

一次提取一条记录:

FETCH cursor_name

INTO variable1,variable2,variable3…;

 

一次提取多条记录:

FETCH cursor_name BULK COLLECT

INTO collect1,collect2,collect3...;

 

·关闭游标

①在提取并处理完所有的数据后,必须关闭游标释放结果集

②语法:

CLOSE  cursor_name;

 

·显式游标的属性

①%ISOPEN

确定游标是否已经打开(True or False)

②%FOUND

返回是否从结果集提取到了数据(True or False)

③%NOTFOUND

返回是否从结果集没有提取到数据(True or False)

④%ROWCOUNT

返回到当前为止已经提取到的实际行数

 

实例:

通过显式游标SELECT读取多行数据:

SQL> DECLARE

  2    CURSOR cur_emp IS

  3      SELECT * FROM emp WHERE deptno=&NO;

  4      emp_rec  emp%ROWTYPE;

  5    BEGIN

  6      IF NOT cur_emp%ISOPEN THEN

  7          OPEN cur_emp;

  8      END IF;

  9 

 10      LOOP

 11        FETCH cur_emp INTO emp_rec;

 12        EXIT WHEN cur_emp%NOTFOUND;

 13        dbms_output.put_line(emp_rec.ename ||','||emp_rec.sal||','||emp_rec.deptno);

 14      END LOOP;

 15      CLOSE cur_emp;

 16     END;

 17  /

SMITH,4600,20

JONES,2975,20

ADAMS,1100,20

FORD,3000,20

PL/SQL procedure successfully completed

 

通过FOR循环读取游标数据:

SQL> DECLARE

  2    CURSOR cur_emp IS

  3    SELECT * FROM emp WHERE deptno=&NO;

  4  BEGIN

  5    FOR emp_rec IN cur_emp LOOP

  6      dbms_output.put_line(emp_rec.ename ||','||emp_rec.sal||','||emp_rec.deptno);

  7    END LOOP;

  8  END;

  9  /

SMITH,4600,20

JONES,2975,20

ADAMS,1100,20

FORD,3000,20

PL/SQL procedure successfully completed

 

三、参数游标

·参数游标是指带有参数的游标

·在定义了参数游标之后,当使用不同参数值多次打开游标时,可以生成不同的结果集

·注意,当定义参数游标时,游标参数只能指定数据类型,而不能指定长度

·当定义参数游标时,一定要在游标子查询的where子句中引用该参数,否则就失去了定义参数游标的意义

·语法:

CURSOR  cursor_name

   [(parameter_name  datatype,…]

IS

   Select_statement;

 

OPEN  cursor_name(parameter_value,……);

 

·实例:

SQL> DECLARE

  2    CURSOR  emp_cur(v_deptno NUMBER) IS

  3      SELECT * FROM emp WHERE deptno=v_deptno;

  4    emp_rec   emp%ROWTYPE;

  5  BEGIN

  6    IF NOT emp_cur%ISOPEN THEN

  7      OPEN emp_cur(30);

  8    END IF;

  9    LOOP

 10      FETCH emp_cur INTO emp_rec;

 11      EXIT WHEN emp_cur%NOTFOUND;

 12      dbms_output.put_line(emp_rec.ename ||','||emp_rec.sal ||','||emp_rec.deptno);

 13    END LOOP;

 14  END;

 15  /

ALLEN,1600,30

WARD,1250,30

MARTIN,1250,30

BLAKE,2850,30

TURNER,1500,30

JAMES,950,30

PL/SQL procedure successfully completed

 

 

四、使用游标处理数据

1.使用游标更新和删除数据

①FOR UPDATE 子句

SELECT …

  FROM…

   FOR UPDATE [ OF column_reference ] [ NOWAIT | WAIT n ];

②WHERE CURRENT OF 子句

UPDATE employees

    SET  salary = ...

    WHERE CURRENT OF c_emp_cursor;

 实例:

使用游标更新数据:

drop table t purge;

create table t(id number(4),num varchar2(15),state number(1));

insert into t(id,num,state) select rownum,abs(dbms_random.random),mod(rownum,2)+1 from dual connect by rownum<=1000;

commit;

 

SQL> DECLARE

  2    CURSOR cur_dt IS

  3       SELECT ID,NUM,state FROM t FOR UPDATE OF NUM;

  4    v_id   t.id%TYPE;

  5    v_num  t.num%TYPE;

  6    v_state  t.state%TYPE;

  7    BEGIN

  8      OPEN cur_dt;

  9      LOOP

 10        FETCH cur_dt

 11          INTO v_id,v_num,v_state;

 12        EXIT WHEN cur_dt%NOTFOUND;

 13        UPDATE t

 14            SET NUM = v_state || LPAD (v_num,14,'0')

 15          WHERE CURRENT OF cur_dt;

 16       END LOOP;

 17       COMMIT;

 18       CLOSE cur_dt;

 19  END;

 20  /

PL/SQL procedure successfully completed

 

实例:

使用游标删除数据:

SQL> DECLARE

  2    CURSOR cur_dt IS

  3      SELECT ID,NUM FROM t FOR UPDATE;

  4    v_id   t.id%TYPE;

  5    v_num t.num%TYPE;

  6    v_type NUMBER;

  7  BEGIN

  8    OPEN cur_dt;

  9    LOOP

 10      FETCH cur_dt

 11        INTO v_id,v_num;

 12        EXIT WHEN cur_dt%NOTFOUND;

 13        v_type :=to_number(SUBSTR(v_num,-1));

 14        IF MOD(v_type,2)=1 THEN

 15          DELETE t WHERE CURRENT OF cur_dt;

 16        END IF;

 17     END LOOP;

 18     COMMIT;

 19     CLOSE cur_dt;

 20  END;

 21  /

PL/SQL procedure successfully completed

 

五、游标FOR循环

①使用FOR循环可以简化游标的使用

②oracle内部会隐含打开、提取和关闭游标

③游标不需要DECLARE

④语法:

FOR record_name IN cursor_name | select_statement   LOOP

Statement1;

Statement2;

……

END LOOP;

 

实例:

SQL> BEGIN

  2    FOR emp_rec IN(SELECT * FROM emp WHERE deptno=&NO) LOOP

  3      dbms_output.put_line(emp_rec.ename ||','||emp_rec.sal ||','||emp_rec.deptno);

  4    END LOOP;

  5  END;

  6  /

SMITH,4600,20

JONES,2975,20

ADAMS,1100,20

FORD,3000,20

PL/SQL procedure successfully completed



六、CURSOR 表达式

①CURSOR 表达式是9i新增的特性

②它用于返回嵌套游标

③使用它可以处理更加复杂的基于多张表的关联数据

1.游标变量

①在PL/SQL中用于存放指向内存地址的指针

②在定义时指定其对应的SELECT语句

③可以使用在OCI、Pro*C/C++、FORMS和REPORTS中

2.游标变量的使用过程

①定义游标

语法:

TYPE ref_type_name IS REF CURSOR [RETURN return_type];

cursor_variable ref_type_name;

解析:

·ref_type_name:用于指定自定义类型名

·RETURN:用于指定返回结果的数据类型

·cursor_variable:用于指定游标变量名

②打开游标

语法:

OPEN cursor_variable FOR select_statement;

·select_statement: 用于指定游标所对应的SELECT语句

③提取游标数据

语法:

FETCH cursor_variable INTO variable1,variable2,...;

FETCH cursor_variable BULK COLLECT

INTO collect1,collect2,...[LIMIT ROWS];

·variable:用于指定接收游标数据的变量

·collect:用于指定接收游标结果的集合变量

④关闭游标

CLOSE cursor_variable;

实例:

SQL> DECLARE

  2    TYPE emp_cursor IS REF CURSOR;

  3    my_cursor  emp_cursor;

  4    v_ename  emp.ename%TYPE;

  5    v_sal  emp.sal%TYPE;

  6    v_deptno  dept.deptno%TYPE :=&deptno;

  7    v_dname  dept.dname%TYPE;

  8  BEGIN

  9    SELECT dname INTO v_dname FROM dept WHERE deptno=v_deptno;

 10    dbms_output.put_line('Department:' || v_dname);

 11    OPEN my_cursor FOR

 12      SELECT ename,sal FROM emp WHERE deptno=v_deptno;

 13    LOOP

 14      FETCH my_cursor

 15        INTO v_ename,v_sal;

 16        EXIT WHEN my_cursor%NOTFOUND;

 17        dbms_output.put_line('--name: ' || v_ename || 'salary:' || v_sal);

 18    END LOOP;

 19    CLOSE my_cursor;

 20  END;

 21  /

Department:RESEARCH

--name: SMITHsalary:4600

--name: JONESsalary:2975

--name: ADAMSsalary:1100

--name: FORDsalary:3000

PL/SQL procedure successfully completed

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值