oracle 游标使用
2014-03-24 17:53
316 查看
游标简介:
游标是PL&SQL中的一种控制结构。可以分为显式游标和隐式游标。pl&sql会为每一条select语句创建隐式游标。但是当我们需要处理多条数据时,我们就需要创建显式游标。
游标的属性:
1、%FOUND --判断游标中是否还有数据,若有,返回true,否则,返回false。
2、%NOTFOUND --与%FOUND 相反
3、%ISOPEN --判断游标是否为打开状态
4、%ROWCOUNT --记录已从游标中取出的记录数
为了以后方便首先我们创建一个测试用表及数据
一、显式游标
显式游标创建方法;CURSOR cursor_name IS select_statement
1、For 循环使用游标,拿到参数的表中的每条数据然后进行操作
2、判断游标中是否有值
执行FETCH语句时,每次返回一个数据行,然后自动将游标移动指向下一个数据行。当检索到最后一行数据时,如果再次执行FETCH语句,将操作失败,并将游标属性%NOTFOUND置为TRUE。所以每次执行完FETCH语句后,检查游标属性%NOTFOUND就可以判断FETCH语句是否执行成功并返回一个数据行,以便确定是否给对应的变量赋了值。%FOUND属性和%NOTFOUND返回的值完全相反
3.使用游标和while循环来显示所有游标中的值(用%found属性)
4,接收用户输入的动物年龄,用for循环和游标,打印出此年龄的所有动物的所有信息(使用循环游标)
5.用游标更新动物年龄
6.用游标查询出动物年龄最大的两个(可以定义一个变量作为计数器控制游标只提取两条数据,也可以在申明游标时把年龄最大的两个动物查询出来放到游标中)
二、隐式游标
显式游标主要是用于对查询语句的处理,尤其是在查询结果为多条记录的情况下;而对于非查询语句,如修改、删除操作,则由ORACLE 系统自动地为这些操作设置游标并创建其工作区,这些由系统隐含创建的游标称为隐式游标,隐式游标的名字为SQL,这是由ORACLE 系统定义的。对于隐式游标的操作,如定义、打开、取值及关闭操作,都由ORACLE 系统自动地完成,无需用户进行处理。用户只能通过隐式游标的相关属性,来完成相应的操作。在隐式游标的工作区中,所存放的数据是与用户自定义的显示游标无关的、最新处理的一条SQL 语句所包含的数据。
格式调用为: SQL%
注:INSERT, UPDATE, DELETE, SELECT 语句中不必明确定义游标。
1.观察更新数据是否已经成功
2.查询中的隐式游标
三、游标变量
首先 , 游标变量和游标是两个不同的概念 . 与游标相似 , 游标变量是指向多行查游标询的结果集的当前行 . 游标是静态的 , 游标变量是动态的 ,. 同时游标变量并不参与与特定的查询绑定 , 所以可以为任何兼容的查询打开游标变量 , 从而提高灵活性 . 而且 , 还可以将新的值赋予游标变量 , 将它作为参数传递给本地和存储过程 . 游标变量针对每个 PL/SQL 用户都是可用的 , 可以在客户端完全使用游标变量 .ORACLE 服务器同样包含 PL/SQL 引擎 , 可以将游标变量在应用和服务器之间进行传递
. 与游标一样,游标变量也是一个指向多行查询结果集合中当前数据行的指针。但与游标不同的是,游标变量是动态的,而游标是静态的。游标只能与指定的查询相连,即固定指向一个查询的内存处理区域,而游标变量则可与不同的查询语句相连,它可以指向不同查询语句的内存处理区域。
1、定义 REF CURSOR 类型
语法格式为:
TYPE ref_type_name IS REF CURSOR [ RETURN return_type];
其中:ref_type_name为新定义的游标变量类型名称;
return_type 为游标变量的返回值类型,它必须为记录变量。
在定义游标变量类型时,可以采用强类型定义和弱类型定义两种。强类型定义必须指定游标变量的返回值类型,
而弱类型定义则不说明返回值类型。
声明一个游标变量的两个步骤:
步骤一:定义一个REF CURSOU数据类型,如:
TYPE ref_cursor_type IS REF CURSOR;
步骤二:声明一个该数据类型的游标变量,如:
cv_ref REF_CURSOR_TYPE
创建两个强类型定义游标变量和一个弱类型游标变量:
与游标一样,游标变量操作也包括打开、提取和关闭三个步骤。
1. 打开游标变量
打开游标变量时使用的是OPEN…FOR 语句。格式为:
OPEN {cursor_variable_name | :host_cursor_variable_name} FOR select_statement;
其中:cursor_variable_name为游标变量,host_cursor_variable_name为PL/SQL主机环境(如OCI: ORACLE Call Interface,Pro*c 程序等)中声明的游标变量。
OPEN…FOR 语句可以在关闭当前的游标变量之前重新打开游标变量,而不会导致CURSOR_ALREAD_OPEN异常错误。新打开游标变量时,前一个查询的内存处理区将被释放。
2. 提取游标变量数据
使用FETCH语句提取游标变量结果集合中的数据。格式为:
FETCH {cursor_variable_name | :host_cursor_variable_name} INTO {variable [, variable]…| record_variable};
其中:cursor_variable_name和host_cursor_variable_name分别为游标变量和宿主游标变量名称;variable和record_variable分别为普通变量和记录变量名称。
3. 关闭游标变量
CLOSE语句关闭游标变量,格式为:CLOSE {cursor_variable_name | :host_cursor_variable_name}
其中:cursor_variable_name和host_cursor_variable_name分别为游标变量和宿主游标变量名称,如果应用程序试图关闭一个未打开的游标变量,则将导致INVALID_CURSOR异常错误。
1.使用游标变量(没有RETURN子句)
2使用游标变量(有RETURN子句)
游标是PL&SQL中的一种控制结构。可以分为显式游标和隐式游标。pl&sql会为每一条select语句创建隐式游标。但是当我们需要处理多条数据时,我们就需要创建显式游标。
游标的属性:
1、%FOUND --判断游标中是否还有数据,若有,返回true,否则,返回false。
2、%NOTFOUND --与%FOUND 相反
3、%ISOPEN --判断游标是否为打开状态
4、%ROWCOUNT --记录已从游标中取出的记录数
为了以后方便首先我们创建一个测试用表及数据
create table T_ZOO ( ID VARCHAR2(20), NAME VARCHAR2(20), AGE VARCHAR2(3) ); insert into T_ZOO (ID, NAME, AGE) values ('1', 'horse', '1'); insert into T_ZOO (ID, NAME, AGE) values ('2', 'fox', '2'); insert into T_ZOO (ID, NAME, AGE) values ('3', 'dog', '2'); insert into T_ZOO (ID, NAME, AGE) values ('4', 'wolf', '4'); insert into T_ZOO (ID, NAME, AGE) values ('5', 'tiger', '3'); insert into T_ZOO (ID, NAME, AGE) values ('6', 'owl', '3'); insert into T_ZOO (ID, NAME, AGE) values ('7', 'python', '4');
一、显式游标
显式游标创建方法;CURSOR cursor_name IS select_statement
1、For 循环使用游标,拿到参数的表中的每条数据然后进行操作
--创建一个存储过程 CREATE OR REPLACE PROCEDURE P_TEST AS BEGIN declare --定义一个游标,内容为查询出所有测试表T_ZOO表中的数据 cursor t_all is select id,name,age from T_ZOO; --定义一个游标变量t_row t_all%ROWTYPE ,该类型为游标t_all中的一行数据类型 t_row t_all%rowtype; begin --使用for循环来使用这个游标 for t_row in t_all loop dbms_output.put_line('动物的id:' ||t_row.id || ',动物的名称:' || t_row.name || ',动物的年龄:' || t_row.age); end loop; end; end;
2、判断游标中是否有值
执行FETCH语句时,每次返回一个数据行,然后自动将游标移动指向下一个数据行。当检索到最后一行数据时,如果再次执行FETCH语句,将操作失败,并将游标属性%NOTFOUND置为TRUE。所以每次执行完FETCH语句后,检查游标属性%NOTFOUND就可以判断FETCH语句是否执行成功并返回一个数据行,以便确定是否给对应的变量赋了值。%FOUND属性和%NOTFOUND返回的值完全相反
CREATE OR REPLACE PROCEDURE P_TEST AS BEGIN declare --定义一个游标,内容为查询出所有测试表T_ZOO表中的数据 cursor t_all is select id,name,age from T_ZOO; --定义一个游标变量t_row t_all%ROWTYPE ,该类型为游标t_all中的一行数据类型 t_row t_all%rowtype; begin --打开游标 open t_all; loop --提取一行数据到t_row fetch t_all into t_row; --判读是否提取到值,没取到值就退出,取到值t_all%notfound 是false,取不到值t_all%notfound 是true exit when t_all%notfound; dbms_output.put_line('数据在表中的行数'||t_all%ROWCOUNT||',动物的id:' ||t_row.id || ',动物的名称:' || t_row.name || ',动物的年龄:' ||t_row.age); end loop; --关闭游标 close t_all; end; end;
3.使用游标和while循环来显示所有游标中的值(用%found属性)
CREATE OR REPLACE PROCEDURE P_TEST AS BEGIN declare --游标声明 cursor t_all is --select语句 select name from t_zoo; --指定行指针 t_row t_all%rowtype; begin --打开游标 open t_all; --给第一行赋值数据 fetch t_all into t_row; --测试是否有数据,并执行循环 while t_all%found loop dbms_output.put_line('动物名称:' || t_row.name); --给下一行赋值数据 fetch t_all into t_row; end loop; close t_all; end; end;
4,接收用户输入的动物年龄,用for循环和游标,打印出此年龄的所有动物的所有信息(使用循环游标)
--定义的语法 CURSOR cursor_name[(parameter[,parameter],...)] IS select_statement; CREATE OR REPLACE PROCEDURE P_TEST AS BEGIN --创建游标,使其可以接受用户输入的值 declare CURSOR t_all(p_deptNo number) is select * from t_zoo where t_zoo.age = p_deptNo; t_row t_zoo%rowtype; begin --调游标时输入差数进行调度 for t_row in t_all(2) loop dbms_output.put_line('动物的id:' || t_row.id || '动物的名称:' || t_row.name || '动物的年龄:' || t_row.age); end loop; end; end;
5.用游标更新动物年龄
CREATE OR REPLACE PROCEDURE P_TEST AS BEGIN declare cursor t_all is select * from t_zoo for update OF age; t_row t_all%rowtype; t_age t_zoo.age%TYPE; begin FOR t_row IN t_all LOOP IF t_row.age<=1 THEN t_age:=t_row.age+1; elsif t_row.age>1 THEN t_age:=t_row.age-1; END IF; --CURRENT OF 用于update 和 delete,你要保证在你进行操作的时候,别人不能对这个数据进行操作。 UPDATE t_zoo SET age=t_age WHERE CURRENT OF t_all; END LOOP; END; end;
6.用游标查询出动物年龄最大的两个(可以定义一个变量作为计数器控制游标只提取两条数据,也可以在申明游标时把年龄最大的两个动物查询出来放到游标中)
CREATE OR REPLACE PROCEDURE P_TEST AS BEGIN declare cursor t_all is select * from t_zoo order by age asc; --计数器 top_two number := 2; t_row t_all%rowtype; begin --打开游标 open t_all; FETCH t_all INTO t_row; while top_two > 0 loop dbms_output.put_line('动物名称:' || t_row.name || ' 年龄:' || t_row.age); --计速器减一 top_two := top_two - 1; FETCH t_all INTO t_row; end loop; --关闭循环 close t_all; end; end;
二、隐式游标
显式游标主要是用于对查询语句的处理,尤其是在查询结果为多条记录的情况下;而对于非查询语句,如修改、删除操作,则由ORACLE 系统自动地为这些操作设置游标并创建其工作区,这些由系统隐含创建的游标称为隐式游标,隐式游标的名字为SQL,这是由ORACLE 系统定义的。对于隐式游标的操作,如定义、打开、取值及关闭操作,都由ORACLE 系统自动地完成,无需用户进行处理。用户只能通过隐式游标的相关属性,来完成相应的操作。在隐式游标的工作区中,所存放的数据是与用户自定义的显示游标无关的、最新处理的一条SQL 语句所包含的数据。
格式调用为: SQL%
注:INSERT, UPDATE, DELETE, SELECT 语句中不必明确定义游标。
1.观察更新数据是否已经成功
CREATE OR REPLACE PROCEDURE P_TEST AS BEGIN --1:任意执行一个update操作,用隐式游标sql的属性%found,%notfound,%rowcount,%isopen 观察update语句的执行情况。 begin update t_zoo set age = 1 WHERE name = 'python'; --判断游标是否为关闭状态,不管执行结果是什么,游标都为关闭状态 if sql%isopen then dbms_output.put_line('游标为打开状态'); else dbms_output.put_line('游标为关闭状态'); end if; --判断游标是否执行 if sql%found then dbms_output.put_line('游标指向了有效行'); else dbms_output.put_line('对不起没有执行'); end if; --判断语句执行是否成功 if sql%notfound then dbms_output.put_line('对不起没有执行'); else dbms_output.put_line('执行成功'); end if; --打印出一共执行了多少条记录 dbms_output.put_line(sql%rowcount); --抛出异常信息 exception --no_data_found判断是否有数据,如果没有抛出异常 when no_data_found then dbms_output.put_line('对不起,没有数据'); --too_many_rows判断是否存在多条数据,如果有抛出异常 when too_many_rows then dbms_output.put_line('对比起,行数过多'); end; end;
2.查询中的隐式游标
CREATE OR REPLACE PROCEDURE P_TEST AS BEGIN declare zooname t_zoo.name%TYPE; begin --判断游标是否打开 if sql%isopen then dbms_output.put_line('第一个判断:游标打开状态'); else dbms_output.put_line('第一个判断:游标关闭状态'); end if; --判断是否有查询结果,由于没有查询所以zooname为null if sql%notfound then dbms_output.put_line('第一个判断:没有值'); else dbms_output.put_line(zooname); end if; --得到游标得到的行数,由于没有sql所有查询出来的值为null dbms_output.put_line(sql%rowcount); --把查询出来的结果赋值给zooname,age=1时报查询值过多的错误age=4时为正常age=5时为没有查询到结果的错误 select name into zooname from t_zoo where age = 1; --查看得到的行数 dbms_output.put_line(sql%rowcount); --判断游标是否打开,不管sql是否执行和有无游标都没有打开 if sql%isopen then dbms_output.put_line('游标打开状态'); else dbms_output.put_line('游标关闭状态'); end if; --打印出得到的值 if sql%notfound then dbms_output.put_line('没有值'); else dbms_output.put_line(zooname); end if; exception when no_data_found then dbms_output.put_line('因为sql没有查询出值,所以报错'); when too_many_rows then dbms_output.put_line('因为sql查询出多个值,所以报错'); end; end;
三、游标变量
首先 , 游标变量和游标是两个不同的概念 . 与游标相似 , 游标变量是指向多行查游标询的结果集的当前行 . 游标是静态的 , 游标变量是动态的 ,. 同时游标变量并不参与与特定的查询绑定 , 所以可以为任何兼容的查询打开游标变量 , 从而提高灵活性 . 而且 , 还可以将新的值赋予游标变量 , 将它作为参数传递给本地和存储过程 . 游标变量针对每个 PL/SQL 用户都是可用的 , 可以在客户端完全使用游标变量 .ORACLE 服务器同样包含 PL/SQL 引擎 , 可以将游标变量在应用和服务器之间进行传递
. 与游标一样,游标变量也是一个指向多行查询结果集合中当前数据行的指针。但与游标不同的是,游标变量是动态的,而游标是静态的。游标只能与指定的查询相连,即固定指向一个查询的内存处理区域,而游标变量则可与不同的查询语句相连,它可以指向不同查询语句的内存处理区域。
1、定义 REF CURSOR 类型
语法格式为:
TYPE ref_type_name IS REF CURSOR [ RETURN return_type];
其中:ref_type_name为新定义的游标变量类型名称;
return_type 为游标变量的返回值类型,它必须为记录变量。
在定义游标变量类型时,可以采用强类型定义和弱类型定义两种。强类型定义必须指定游标变量的返回值类型,
而弱类型定义则不说明返回值类型。
声明一个游标变量的两个步骤:
步骤一:定义一个REF CURSOU数据类型,如:
TYPE ref_cursor_type IS REF CURSOR;
步骤二:声明一个该数据类型的游标变量,如:
cv_ref REF_CURSOR_TYPE
创建两个强类型定义游标变量和一个弱类型游标变量:
DECLARE TYPE deptrecord IS RECORD( Deptno departments.department_id%TYPE, Dname departments.department_name%TYPE, Loc departments.location_id%TYPE ); TYPE deptcurtype IS REF CURSOR RETURN departments%ROWTYPE; TYPE deptcurtyp1 IS REF CURSOR RETURN deptrecord; TYPE curtype IS REF CURSOR; Dept_c1 deptcurtype;--强类型游标变量 Dept_c2 deptcurtyp1;--强类型游标变量 Cv curtype;--弱类型游标变量
与游标一样,游标变量操作也包括打开、提取和关闭三个步骤。
1. 打开游标变量
打开游标变量时使用的是OPEN…FOR 语句。格式为:
OPEN {cursor_variable_name | :host_cursor_variable_name} FOR select_statement;
其中:cursor_variable_name为游标变量,host_cursor_variable_name为PL/SQL主机环境(如OCI: ORACLE Call Interface,Pro*c 程序等)中声明的游标变量。
OPEN…FOR 语句可以在关闭当前的游标变量之前重新打开游标变量,而不会导致CURSOR_ALREAD_OPEN异常错误。新打开游标变量时,前一个查询的内存处理区将被释放。
2. 提取游标变量数据
使用FETCH语句提取游标变量结果集合中的数据。格式为:
FETCH {cursor_variable_name | :host_cursor_variable_name} INTO {variable [, variable]…| record_variable};
其中:cursor_variable_name和host_cursor_variable_name分别为游标变量和宿主游标变量名称;variable和record_variable分别为普通变量和记录变量名称。
3. 关闭游标变量
CLOSE语句关闭游标变量,格式为:CLOSE {cursor_variable_name | :host_cursor_variable_name}
其中:cursor_variable_name和host_cursor_variable_name分别为游标变量和宿主游标变量名称,如果应用程序试图关闭一个未打开的游标变量,则将导致INVALID_CURSOR异常错误。
CREATE OR REPLACE PROCEDURE P_TEST AS BEGIN DECLARE TYPE t_parameter IS RECORD( t_id t_zoo.id%TYPE, t_name t_zoo.name%TYPE); --申明一个强类型游标 start---- TYPE q_type_avow IS REF CURSOR RETURN t_parameter; q_type q_type_avow; q_job t_parameter; --申明一个强类型游标 end---- --申明一个弱类型游标 start---- Type r_type_avow IS REF CURSOR; r_type r_type_avow; r_job t_parameter; --申明一个弱类型游标 end---- BEGIN ---使用强类型 start --打开游标变量 OPEN q_type FOR SELECT t_zoo.id, t_zoo.name FROM t_zoo; FETCH q_type INTO q_job; WHILE q_type%FOUND LOOP DBMS_OUTPUT.PUT_LINE(q_job.t_id || '名称: ' || q_job.t_name); FETCH q_type INTO q_job; END LOOP; CLOSE q_type; DBMS_OUTPUT.PUT_LINE('-------------------------'); --使用强类型 end ---使用弱类型 start OPEN r_type FOR SELECT t_zoo.id, t_zoo.name FROM t_zoo; FETCH r_type INTO r_job; WHILE r_type%FOUND LOOP DBMS_OUTPUT.PUT_LINE(r_job.t_id || '名称: ' || r_job.t_name); FETCH r_type INTO r_job; END LOOP; CLOSE r_type; ---使用弱类型 end END; end;
1.使用游标变量(没有RETURN子句)
CREATE OR REPLACE PROCEDURE P_TEST AS BEGIN DECLARE --定义一个游标数据类型 TYPE r_type_avow IS REF CURSOR; --声明一个游标变量 r_type r_type_avow; --声明两个记录变量 r_zoo_row t_zoo%ROWTYPE; r_zoo_row1 t_zoo%ROWTYPE; BEGIN OPEN r_type FOR SELECT * FROM t_zoo; LOOP FETCH r_type INTO r_zoo_row; EXIT WHEN r_type%NOTFOUND; DBMS_OUTPUT.PUT_LINE(r_zoo_row.name || 'id是:' || r_zoo_row.id|| '年龄是:' || r_zoo_row.age); END LOOP; --将同一个游标变量对应到另一个SELECT语句 OPEN r_type FOR SELECT * FROM t_zoo; LOOP FETCH r_type INTO r_zoo_row1; EXIT WHEN r_type%NOTFOUND; DBMS_OUTPUT.PUT_LINE(r_zoo_row1.name || '年龄:' || r_zoo_row1.age); END LOOP; CLOSE r_type; END; end;
2使用游标变量(有RETURN子句)
CREATE OR REPLACE PROCEDURE P_TEST AS BEGIN DECLARE --定义一个与employees表中的这几个列相同的记录数据类型 TYPE t_parameter IS RECORD( t_name t_zoo.name%TYPE, t_age t_zoo.age%TYPE, t_id t_zoo.id%TYPE); --声明一个该记录数据类型的记录变量 q_job t_parameter; --定义一个游标数据类型 TYPE q_type_avow IS REF CURSOR RETURN t_parameter; --声明一个游标变量 q_type q_type_avow; BEGIN OPEN q_type FOR SELECT name,age,id FROM t_zoo; LOOP FETCH q_type INTO q_job; EXIT WHEN q_type%NOTFOUND; DBMS_OUTPUT.PUT_LINE('动物名称:'||q_job.t_name ||' 动物id:'||q_job.t_id ||' 动物年龄:'||q_job.t_age); END LOOP; CLOSE q_type; END; end;
相关文章推荐
- Oracle 游标使用全解
- Oracle 游标使用全解
- oracle游标的定义使用
- ORACLE/PLSQL 游标的简单使用
- Oracle游标使用攻略
- Oracle使用游标查询指定数据表的所有字段名称组合而成的字符串
- Oracle游标中直接使用日期变量的问题解决
- oracle中游标的使用,示例
- Oracle 游标使用全解
- Oracle&nbsp;游标使用全解
- oracle中使用游标实现多重循环
- Oracle游标使用
- ORACLE游标使用
- Oracle 游标使用大全
- Oracle 游标使用总结
- Oracle 游标使用1
- Oracle 中使用 fetch bulk collect into 批量效率的读取游标数据
- Oracle 游标使用大全2
- oracle 中游标和存储过程的使用
- oracle 游标使用(隐式游标)