游標(biāo)操作的優(yōu)化:
成都創(chuàng)新互聯(lián)堅(jiān)持“要么做到,要么別承諾”的工作理念,服務(wù)領(lǐng)域包括:網(wǎng)站設(shè)計(jì)、成都網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣等服務(wù),滿足客戶于互聯(lián)網(wǎng)時(shí)代的云霄網(wǎng)站設(shè)計(jì)、移動(dòng)媒體設(shè)計(jì)的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡(luò)建設(shè)合作伙伴!
-- 有一個(gè)表格,存儲(chǔ)的是用戶的名字,將 emp 表中所有的用戶名轉(zhuǎn)換成小寫,再寫入這個(gè)表格
create table ename_emp(
ename varchar2(50)
);
-- 下面這個(gè)游標(biāo)的操作,需要 43s時(shí)間才能完成
declare
begin
for i in (select ename from emp_liebiao) loop
insert into ename_emp values(lower(i.ename));
commit;
end loop;
end;
-- 因?yàn)橛螛?biāo)是以行為單位進(jìn)行數(shù)據(jù)的操作的,所有游標(biāo)的效率是比較慢的,而且游標(biāo)需要消耗的內(nèi)存也是比較多的,我們需要將游標(biāo)以行進(jìn)行操作的方式,修改成一次性操作所有數(shù)據(jù)的批量的方式。
批量操作在游標(biāo)里面 叫做 bulk collect
第一步,創(chuàng)建一個(gè)表類型
type 表類型的名字 is table of 表名.列名 %type;
變量名 表類型的名字;
第三步,創(chuàng)建一個(gè)游標(biāo),讀取某個(gè)查詢的結(jié)果
cursor 游標(biāo)名字 is select 查詢語句 ;
第四步,打開游標(biāo)
open 游標(biāo)名字;
第五步,捕獲游標(biāo)的數(shù)據(jù),將內(nèi)容給到表類型的變量進(jìn)行保存
fetch 游標(biāo)名字 bulk collect into 變量名字 ;
第六步,使用 forall 語句,對數(shù)據(jù)進(jìn)行批量的操作
forall i in 變量 .first .. 變量 .last DML 語句操作 ;
第七步,關(guān)閉游標(biāo)
close 游標(biāo)名字 ;
declare
-- 創(chuàng)建表類型
type biao is table of emp_liebiao.ename%type;
b biao;
-- 創(chuàng)建游標(biāo)
cursor m is select ename from emp_liebiao;
begin
-- 打開游標(biāo)
open m;
-- 將游標(biāo)的內(nèi)容批量的給到變量
fetch m bulk collect into b;
-- 使用forall批量修改數(shù)據(jù)
forall i in b.first .. b.last insert into ename_emp values(lower(b(i)));
commit;
-- 關(guān)閉游標(biāo)
close m;
end;
練習(xí):批量修改用戶的編號,讓編號+工資等級+部門,形成一個(gè)新的編號,存入下面的表格中,使用 bulk collect 來實(shí)現(xiàn)。
2000以下是 C ,2000-3000是 B ,3000以上是 A ,
例如 SMITH , 新編號應(yīng)該是 7369_C_20
create table empno_emp(
empno varchar2(50)
);
declare
type biao is table of emp_liebiao%rowtype;
b biao;
cursor m is select * from emp_liebiao;
begin
open m;
fetch m bulk collect into b;
forall i in b.first..b.last
insert into empno_emp values(
b(i).empno||'_'||decode(sign(b(i).sal-2000)+sign(b(i).sal-3000),-2,'C',2,'A','B')||'_'||b(i).deptno
);
commit;
close m;
end;
一
游標(biāo)是什么
游標(biāo)字面理解就是游動(dòng)的光標(biāo)。
用數(shù)據(jù)庫語言來描述:游標(biāo)是映射在結(jié)果集中一行數(shù)據(jù)上的位置實(shí)體,有了游標(biāo),用戶就可以訪問結(jié)果集中的任意一行數(shù)據(jù)了,將游標(biāo)放置到某行后,即可對該行數(shù)據(jù)進(jìn)行操作,例如提取當(dāng)前行的數(shù)據(jù)等。
二
游標(biāo)的分類
顯式游標(biāo)和隱式游標(biāo)
顯式游標(biāo)的使用需要4步:
1.
聲明游標(biāo)
CURSOR
mycur(vartype
number)
is
select
emp_no,emp_zc
from
cus_emp_basic
where
com_no
=
vartype;
2.
打開游標(biāo)
open
mycur(000627)
注:000627是參數(shù)
3.
讀取數(shù)據(jù)
fetch
mycur
into
varno,
varprice;
4.
關(guān)閉游標(biāo)
close
mycur;
三
游標(biāo)的屬性
oracle
游標(biāo)有4個(gè)屬性:%ISOPEN,%FOUND,%NOTFOUND,%ROWCOUNT。
%ISOPEN判斷游標(biāo)是否被打開,如果打開%ISOPEN等于true,否則等于false;
%FOUND
%NOTFOUND判斷游標(biāo)所在的行是否有效,如果有效,則%FOUNDD等于true,否則等于false;
%ROWCOUNT返回當(dāng)前位置為止游標(biāo)讀取的記錄行數(shù)。
四
示例
set
serveroutput
on;
declare
varno
varchar2(20);
varprice
varchar2(20);
CURSOR
mycur(vartype
number)
is
select
emp_no,emp_zc
from
cus_emp_basic
where
com_no
=
vartype;
begin
if
mycur%isopen
=
false
then
open
mycur(000627);
end
if;
fetch
mycur
into
varno,varprice;
while
mycur%found
loop
dbms_output.put_line(varno||','||varprice);
if
mycur%rowcount=2
then
exit;
end
if;
fetch
mycur
into
varno,varprice;
end
loop;
close
mycur;
end;
PL/SQL記錄的結(jié)構(gòu)和C語言中的結(jié)構(gòu)體類似,是由一組數(shù)據(jù)項(xiàng)構(gòu)成的邏輯單元。
PL/SQL記錄并不保存在數(shù)據(jù)庫中,它與變量一樣,保存在內(nèi)存空間中,在使用記錄時(shí)候,要首先定義記錄結(jié)構(gòu),然后聲明記錄變量。可以把PL/SQL記錄看作是一個(gè)用戶自定義的數(shù)據(jù)類型。
set
serveroutput
on;
declare
type
person
is
record
(
empno
cus_emp_basic.emp_no%type,
empzc
cus_emp_basic.emp_zc%type);
person1
person;
cursor
mycur(vartype
number)is
select
emp_no,emp_zc
from
cus_emp_basic
where
com_no=vartype;
begin
if
mycur%isopen
=
false
then
open
mycur(000627);
end
if;
loop
fetch
mycur
into
person1;
exit
when
mycur%notfound;
dbms_output.put_line('雇員編號:'||person1.empno||',地址:'||person1.empzc);
end
loop;
close
mycur;
end;
典型游標(biāo)for
循環(huán)
游標(biāo)for循環(huán)示顯示游標(biāo)的一種快捷使用方式,它使用for循環(huán)依次讀取結(jié)果集中的行數(shù)據(jù),當(dāng)form循環(huán)開始時(shí),游標(biāo)自動(dòng)打開(不需要open),每循環(huán)一次系統(tǒng)自動(dòng)讀取游標(biāo)當(dāng)前行的數(shù)據(jù)(不需要fetch),當(dāng)退出for循環(huán)時(shí),游標(biāo)被自動(dòng)關(guān)閉(不需要使用close)。使用游標(biāo)for循環(huán)的時(shí)候不能使用open語句,fetch語句和close語句,否則會(huì)產(chǎn)生錯(cuò)誤。
set
serveroutput
on;
declare
cursor
mycur(vartype
number)is
select
emp_no,emp_zc
from
cus_emp_basic
where
com_no=vartype;
begin
for
person
in
mycur(000627)
loop
dbms_output.put_line('雇員編號:'||person.emp_no||',地址:'||person.emp_zc);
end
loop;
end;
1.游標(biāo)定義:\x0d\x0acursor XXXA is\x0d\x0a SELECT 語句;\x0d\x0aXXXB cursorName%rowtype;\x0d\x0a\x0d\x0aXXXA: 游標(biāo)名\x0d\x0aXXXB: 游標(biāo)行數(shù)據(jù)定義\x0d\x0a\x0d\x0a2. 打開游標(biāo):\x0d\x0a-- 打開之前最好先關(guān)一下,防止上次發(fā)生異常沒有關(guān)掉而引發(fā)不必要的異常\x0d\x0a IF XXXA%ISOPEN THEN\x0d\x0a CLOSE XXXA;\x0d\x0a END IF;\x0d\x0a\x0d\x0aOpen XXXA ;\x0d\x0a Loop\x0d\x0a Fetch XXXA into XXXB;\x0d\x0a exit when XXXA%NOTFOUND;\x0d\x0a... ... 處理邏輯\x0d\x0a end loop;\x0d\x0a close XXXA;
For 循環(huán)游標(biāo)
(1)定義游標(biāo)
(2)定義游標(biāo)變量
(3)使用for循環(huán)來使用這個(gè)游標(biāo)
declare
--類型定義
cursor c_job
is
select empno,ename,job,sal
from emp
where job='MANAGER';
--定義一個(gè)游標(biāo)變量v_cinfo c_emp%ROWTYPE ,該類型為游標(biāo)c_emp中的一行數(shù)據(jù)類型
c_row c_job%rowtype;
begin
for c_row in c_job loop
dbms_output.put_line(c_row.empno||'-'||c_row.ename||'-'||c_row.job||'-'||c_row.sal);
end loop;
end;
Fetch游標(biāo)
使用的時(shí)候必須要明確的打開和關(guān)閉
declare
--類型定義
cursor c_job
is
select empno,ename,job,sal
from emp
where job='MANAGER';
--定義一個(gè)游標(biāo)變量
c_row c_job%rowtype;
begin
open c_job;
loop
--提取一行數(shù)據(jù)到c_row
fetch c_job into c_row;
--判讀是否提取到值,沒取到值就退出
--取到值c_job%notfound 是false
--取不到值c_job%notfound 是true
exit when c_job%notfound;
dbms_output.put_line(c_row.empno||'-'||c_row.ename||'-'||c_row.job||'-'||c_row.sal);
end loop;
--關(guān)閉游標(biāo)
close c_job;
end;