一、游标的定义:游标是一个容器,用来记录查询结果集的,本质是一块内存,如果不释放,就会占用内存,这就是为什么open之后还要close操作。
二、游标的优缺点:
1.优点:游标的一个常见用途就是保存查询结果,以便以后使用。游标的结果集是由SELECT语句产生,如果处理过程需要重复使用一个记录集,那么创建一次游标而重复使用若干次,比重复查询数据库要快的多;如果我们要对查询出的结果做特殊处理,然后在进行下一步操作(比如将数据存新表),使用游标也是比较方便的;
2.缺点:当数据量非常大时,使用游标会带来很大的效率问题,因为游标其实是相当于把磁盘数据整体放入了内存中,游标数据量大的话则会造成内存不足;另外系统上跑的不只是一个业务,游标使用会对行加锁,可能影响其他业务的正常进行。所以慎用游标
三、游标的具体使用:
1.显示游标
显示游标的属性,通常用来获取一个游标的状态信息
1.1、isopen(Boolean):如果游标是打开的,那么这个游标的值为true
1.2、notfound(Boolean):如果最近一次的fetch操作没有返回一行数据,那么此值为true
1.3、found(Boolean):如果最近一次的fetch操作返回一行数据,那么此值为true
1.4、rowcount(Number):返回行数的总和,使用时的格式:”游标名%rowcount“,注意不能在游标打开之前和游标关闭之后使用此属性。
显示游标的使用步骤:
a.定义游标
b.打开游标
c.提取游标数据
d.关闭游标
具体使用:(从两张表中按照一些规定抽出部分数据)
declare
orgVar varchar2(30);
psuhDateVar varchar2(30);
memLevelVar varchar2(30);
lowVar varchar2(30);
validVar varchar2(30);
effectiveVar varchar2(30);
cursor OrgAndExpireData is
select a.config_org,
a.push_date,
case a.mem_level
when '0' then
'1,2,3,4,5,6'
else
a.mem_level
end mem_level,
a.lowest_source_expire,
a.is_valid,
a.effective_date
from integral_expire_rules a
left join push_date_table b
on a.config_org = b.config_org
where a.is_valid = '1'
and to_char(a.effective_date, 'yyyy-MM-dd') <=
to_char(sysdate, 'yyyy-MM-dd')
and a.push_date = to_char(sysdate, 'dd');
-- and (to_char(b.push_finish_date,'yyyy-MM')!=to_char(sysdate,'yyyy-MM') or b.push_finish_date is null);
begin
open OrgAndExpireData;
loop
fetch OrgAndExpireData
into orgVar, psuhDateVar, memLevelVar, lowVar, validVar, effectiveVar;
exit when OrgAndExpireData%notfound;
dbms_output.put_line(orgVar || '.....' || psuhDateVar);
end loop;
close OrgAndExpireData;
end;
2、隐式游标
使用隐式游标时,不需要我们手动执行open,fetch,close操作了,PL/SQL语言提供了游标FOR循环语句,自动执行游标的OPEN、FETCH、CLOSE语句和循环语句的功能;
隐式游标是不需要定义的,系统默认等同为游标的,入一个select语句,DML语句,都会打开一个游标。
2.1.当进入循环时,游标For循环语句自动打开游标,并提取第一行游标数据;
2.2.当程序处理完当前所提取的数据而进入下一次循环时,游标FOR循环语句自动提取下一行数据供程序处理;
2.3.当程序处理完当前所提取的数据而进入下一次循环时,游标for循环语句自动提取下一行数据供程序处理;
declare
cursor OrgAndExpireData is
select *
from integral_expire_rules a left join push_date_table b
on a.config_org=b.config_org
where a.is_valid='1'
and to_char(a.effective_date,'yyyy-MM-dd')<=to_char(sysdate,'yyyy-MM-dd')
and a.push_date=to_char(sysdate,'dd');
-- and (to_char(b.push_finish_date,'yyyy-MM')!=to_char(sysdate,'yyyy-MM') or b.push_finish_date is null);
begin
for storeVar in OrgAndExpireData loop
dbms_output.put_line(storeVar.rule_name||'....'||storeVar.mem_level||'..'||storeVar.is_valid);
end loop;
end;
参考博客:
https://www.zhihu.com/question/19777435/answer/37060426
https://blog.csdn.net/haiross/article/details/42967213
补充存储过程相关:
1.select into form 和 insert into select 的区别
1.1 insert into select
语句形式为:Insert into Table2(field1,field2,...) select value1,value2,... from Table1
或者:Insert into Table2 select * from Table1
@1要求目标表Table2必须存在,并且字段field,field2...也必须存在
@2注意语法,不要加values,和插入一条数据的sql混了,不要写成:
Insert into Table2(field1,field2,...) values (select value1,value2,... from Table1)
1.2 select into form
语句形式为:SELECT vale1, value2 into Table2 from Table1
要求目标表Table2不存在,因为在插入时会自动创建表Table2,并将Table1中指定字段数据复制到Table2中
2.存储过程中不能直接使用ddl语句,如truncate table,需要这种形式:
execute immediate 'truncate table emp';注意,引号内不能加分号