mysql隐式游标_转载整理:显式游标和隐式游标和动态游标

显式游标:

游标的定义和操作

游标的使用分成以下4个步骤。

1.声明游标

在DECLEAR部分按以下格式声明游标:

CURSOR 游标名[(参数1 数据类型[,参数2 数据类型...])]

IS SELECT语句;

参数是可选部分,所定义的参数可以出现在SELECT语句的WHERE子句中。如果定义了参数,则必须在打开游标时传递相应的实际参数。

SELECT语句是对表或视图的查询语句,甚至也可以是联合查询。可以带WHERE条件、ORDER BY或GROUP BY等子句,但不能使用INTO子句。在SELECT语句中可以使用在定义游标之前定义的变量。

2.打开游标

在可执行部分,按以下格式打开游标:

OPEN 游标名[(实际参数1[,实际参数2...])];

打开游标时,SELECT语句的查询结果就被传送到了游标工作区。

3.提取数据

在可执行部分,按以下格式将游标工作区中的数据取到变量中。提取操作必须在打开游标之后进行。

FETCH 游标名 INTO 变量名1[,变量名2...];

FETCH 游标名 INTO 记录变量;

游标打开后有一个指针指向数据区,FETCH语句一次返回指针所指的一行数据,要返回多行需重复执行,可以使用循环语句来实现。控制循环可以通过判断游标的属性来进行。

下面对这两种格式进行说明:

第一种格式中的变量名是用来从游标中接收数据的变量,需要事先定义。变量的个数和类型应与SELECT语句中的字段变量的个数和类型一致。

第二种格式一次将一行数据取到记录变量中,需要使用%ROWTYPE事先定义记录变量,这种形式使用起来比较方便,不必分别定义和使用多个变量。

定义记录变量的方法如下:

变量名 表名|游标名%ROWTYPE;

其中的表必须存在,游标名也必须先定义。

4.关闭游标

CLOSE 游标名;

显式游标打开后,必须显式地关闭。游标一旦关闭,游标占用的资源就被释放,游标变成无效,必须重新打开才能使用。

现在通过一个例子来学习一下显示游标的使用方法:

有一个表原来结构是如下的

create table EXCHANGERATE

(

QUARTER VARCHAR2(20),

RATE NUMBER(10,4),

DESCRIPTION VARCHAR2(900),

ID VARCHAR2(10) not null,

CURRENCY VARCHAR2(100)

)

这是一个汇率表里面维护着的是季度 币种和汇率的关系,现在有一个新的需求是在原来表的基础上增加一列名字为currentmonth,变为季度、季度中月份、 币种和汇率的关系,

并且使原来每个季度对应的币种和汇率变成每个季度 对应该季度月份 币种和汇率,每个月的默认值为原来季度对应的值。

例如 原来 2013Q2 CNY 6.2

现在我们要变为2013Q2 2013-04 CNY 6.2  2013Q2 2013-05 CNY 6.2

2013Q2 2013-06 CNY 6.2  三条记录。

通过分析以上需求,我们首先要增加一列:

alter table exchangerate add currentmonth varchar2(20);

然后我们通过在匿名块中通过显示游标来实现以上需求:

1 declare2

3 v_year varchar2(20);4 v_month number;5 p_rate exchangerate%rowtype;6 cursor c_rate is select * from exchangerate t where t.currentmonth is null;7 begin8 open c_rate;9 loop10 fetch c_rate into p_rate;11 v_year:=substr(p_rate.quarter, 0, 4);12 v_month:=(to_number(substr(p_rate.quarter,6,1)) - 1) * 3;13 for i in 1 .. 3loop14

15 insert into exchangerate(id,quarter,currentmonth,rate,currency,Description)16 values(SEQUENCE_EXCHANGERATE.nextval,p_rate.quarter,17 to_char(to_date(v_year||(v_month+i),'yyyyMM'),'yyyy-MM'),p_rate.rate,p_rate.currency,p_rate.description);18

19 end loop;20 exit when c_rate%notfound;21 end loop;22 close c_rate;23 end;24 /

25 复制代码26 我们把上面的例子有游标的for循环来改写一下。27

28

29

30 显式游标的for循环31

32 复制代码33 declare34

35 v_year varchar2(20);36 v_month number;37

38 cursor c_rate is select * from exchangerate t where t.currentmonth is null;39

40 begin41

42 forp_rate in c_rate loop43

44 v_year:=substr(p_rate.quarter, 0, 4);45

46 v_month:=(to_number(substr(p_rate.quarter,6,1)) - 1) * 3;47

48 for i in 1 .. 3loop49

50 insert into exchangerate(id,quarter,currentmonth,rate,currency,Description)51 values(SEQUENCE_EXCHANGERATE.nextval,p_rate.quarter,52 to_char(to_date(v_year||(v_month+i),'yyyyMM'),'yyyy-MM'),p_rate.rate,p_rate.currency,p_rate.description);53

54 end loop;55

56 end loop;57

58 end;59

60 /

我们可以看到游标FOR循环确实很好的简化了游标的开发,我们不在需要open、fetch和close语句,不在需要用%FOUND属性检测是否到最后一条记录,这一切Oracle隐式的帮我们完成了。

隐式游标的for循环

1 declare2

3 v_year varchar2(20);4 v_month number;5

6 begin7

8 for p_rate in (select * from exchangerate t where t.currentmonth is null) loop9

10 v_year:=substr(p_rate.quarter, 0, 4);11 v_month:=(to_number(substr(p_rate.quarter,6,1)) - 1) * 3;12 for i in 1 .. 3loop13

14 insert into exchangerate(id,quarter,currentmonth,rate,currency,Description)15 values(SEQUENCE_EXCHANGERATE.nextval,p_rate.quarter,16 to_char(to_date(v_year||(v_month+i),'yyyyMM'),'yyyy-MM'),p_rate.rate,p_rate.currency,p_rate.description);17

18 end loop;19

20 end loop;21

22 end;23 /

显示游标中游标参数的传递

例子:就以上面的表来说 加入我们在定义游标时不确定查询条件中的值,这时我们可以通过游标参数来解决

1 declare2

3 v_year varchar2(20);4 v_month number;5 p_rate exchangerate%rowtype;6

7 cursor c_rate(p_quarter varchar2) --声明游标带参数8 is9 select * from exchangerate t where t.quarter<=p_quarter;10

11 begin12 open c_rate(p_quarter=>'2011Q3');--打开游标,传递参数值13 loop14

15 fetch c_rate into p_rate;16

17 update exchangerate set rate=p_rate.rate+1 where id=p_rate.id;18

19

20 exit when c_rate%notfound;21

22 end loop;23

24 close c_rate;25

26 end;

游标变量

游标是数据库中一个命名的工作区,当游标被声明后,他就与一个固定的SQL想关联,在编译时刻是已知的,是静态的.它永远指向一个相同的查询工作区.

游标变量是动态的可以在运行时刻与不同的SQL语句关联,在运行时可以取不同的SQL语句.它可以引用不同的工作区.

如何定义游标类型

TYPE ref_type_name IS REF CURSOR

[RETURN return_type];

声明游标变量

cursor_name ref_type_name;

ref_type_name 是后面声明游标变量时要用到的我们的游标类型(自定义游标类型,即CURSOR是系统默认的,ref_type_name是我们定义的 );

return_type代表数据库表中的一行,或一个记录类型

TYPE ref_type_name IS REF CURSOR RETURN EMP%TYPE

RETURN 是可选的,如果有是强类型,可以减少错误,如果没有return是弱引用,有较好的灵活性.

游标变量的操作

例子:

1 declare2

3 v_year varchar2(20);4 v_month number;5 p_rate exchangerate%rowtype;6

7 type rate is ref cursor;--定义游标变量8 c_rate rate; --声明游标变量9

10 begin11

12

13 open c_rate for select * from exchangerate t where t.quarter='2011Q3';--打开游标变量 loop14

15 fetch c_rate into p_rate;--提取游标变量16

17 update exchangerate set rate=p_rate.rate+1 where id=p_rate.id;18

19 exit when c_rate%notfound;20

21 end loop;22

23 --将同一个游标变量对应到另一个SELECT语句24

25 open c_rate for select * from exchangerate t where t.quarter='2011Q2';--打开游标变量 loop26

27 fetch c_rate into p_rate;--提取游标变量28

29 update exchangerate set rate=p_rate.rate-1 where id=p_rate.id;30

31 exit when c_rate%notfound;32

33 end loop;34 close c_rate;--关闭游标变量35

36 end;

游标表达式

Oracle在SQL语言中提供了一个强有力的工具:游标表达式。一个游标表达式从一个查询中返回一个内嵌的游标。在这个内嵌游标的结果集中,每一行数据包含了在SQL查询中的可允许的数值范围;它也能包含被其他子查询所产生的游标。

因此,你能够使用游标表达式来返回一个大的和复杂的,从一张或多张表获取的数据集合。游标表达式的复杂程度,取决于查询和结果集。然而,了解所有从Oracle RDBMS提取数据的可能途径,还有大有好处的。

你能够在以下任何一种情况使用游标表达式:

(1)、 显式游标声明

(2)、动态SQL查询。

(3)、REF CURSOR 声明和变量。

你不能在一个隐式查询中使用游标表达式。

游标表达式的语法是相当简单的:

CURSOR (查询语句)

当Oracle从父游标或外围游标那里检取包含游标表达式的数据行时,Oracle就会隐式地打开一个内嵌的游标,这个游标就是被上述的游标表达式所定义。在以下情况发生时,这个内迁游标将会被关闭:

(1)、你显式地关闭这个游标。

(2)、外围或父游标被重新执行,关闭或撤销。

(3)、当从父游标检取数据时,发生异常。内嵌游标就会与父游标一起被关闭。

使用游标表达式

你可以通过两种不同的,但是非常有用的方法来使用游标表达式:

1.  在一个外围查询中把字查询作为一列来检取数据。

2.  把一个查询转换成一个结果集,而这个结果集就可以被当成一个参数传递给一个流型或变换函数。

例子:

1 CREATE OR REPLACE PROCEDURE emp_report(p_locid NUMBER)2 IS3 TYPE refcursor IS REF CURSOR;4 CURSOR all_in_one IS5 SELECT l.city, CURSOR(6 SELECT d.department_name, CURSOR (7 SELECT e.last_name8 FROM employees e9 WHERE e.DEPARTMENT_ID =d.DEPARTMENT_ID10 ) as ename11 FROM departments d12 WHERE d.LOCATION_ID =l.LOCATION_ID13 ) as dname14 FROM locations l15 WHERE l.location_id =p_locid;16 departments_cur refcursor;17 employees_cur refcursor;18 v_city locations.city%type;19 v_dname departments.department_name%type;20 v_ename employees.last_name%type;21 i integer :=1;22 j integer :=1;23 k integer :=1;24 BEGIN25 OPEN all_in_one;26 LOOP27 FETCH all_in_one INTO v_city, departments_cur;28 EXIT WHEN all_in_one%NOTFOUND;29 LOOP30 FETCH departments_cur INTO v_dname, employees_cur;31 EXIT WHEN departments_cur%NOTFOUND;32 LOOP33 FETCH employees_cur INTO v_ename;34 EXIT WHEN employees_cur%NOTFOUND;35 dbms_output.put_line(i || ' , ' || j || ' , ' || k || '----' || v_city || ' ,' || v_dname || ' ,' ||v_ename );36 k := k + 1;37 END LOOP;38 j := j + 1;39 END LOOP;40 i := i + 1;41 END LOOP;42 END;43 /

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值