1.光標的引入
光標(遊標):就是一個結果集(ResultSet)。
2.光標的語法
CURSOR 光標名 [(參數名 數據類型[,參數名 數據類型]...)]
IS SELECT 語句;
eg:cursor c1 is select ename from emp;
打開光標:
- open c1;(打開光標執行查詢)
取一行光標的值:
- fetch c1 into pename;(取一行到變量中)
關閉光標:
- close c1;(關閉遊標釋放資源)
說明:fetch的作用:
-把當前指針指向的記錄返回
-將指針指向下一條記錄
3.光標實例
(1).查詢員工工資:
set serveroutput on
declare
cursor cemp is select ename,salfrom emp;
pename emp.ename%type;
psal emp.sal%type;
begin
open cemp;
loop
fetch cemp into pename,psal;
exit when cemp%notfound;
dbms_output.put_line(pename||'的薪水是'||psal);
end loop;
close cemp;
end;
/
(2).給員工漲工資:
set serveroutput on
declare
cursor cemp is select empno,empjob from emp;
pempno emp.empno%type;
pjob emp.empjob%type;
begin
open cemp;
loop
fetch cemp into pempno,pjob;
exit when cemp%notfound;
if pjob='PRESIDENT' then update empset sal=sal+1000 where empno=pempno;
elsif pjob='MANAGER' then updateemp set sal=sal+800 where empno=pempno;
else update emp set sal=sal+400where empno=pempno;
end if;
end loop;
close cemp;
commit;
dbms_output.put_line('漲工資完成');
end;
/
Tips:oracle數據庫中,默認開啓事務。
同時開啓兩個事務,要考慮事務的隔離性。
對於oracle,默認的事務隔離級別是read committed
如果pl/sql程序對數據進行了更改,需要commit
4.光標的屬性
%found %notfound(判斷光標是否取到值(fetch 光標 into 變量))
%isopen(判斷光標是否打開)
%rowcount(得到光標影響行數)
set serveroutput on
declare
cursor c_emp is selectempno,empjob from emp;
p_no emp.empno%type;
p_job emp.empjob%type;
begin
open c_emp;
--%isopen
if c_emp%isopen thendbms_output.put_line('光標已經打開');
else dbms_output.put_line('光標沒有打開');
end if;
--%rowcount
loop
fetch c_emp into p_no,p_job;
exit when c_emp%notfound;
dbms_output.put_line('rowcount:'||c_emp%rowcount);
end loop;
close c_emp;
end;
/
5.光標的限制
默認的一個會話最多可以打開300個光標
查看系統Curoser參數
Show Parameter cursor;
修改Cursor參數
Alter System set Cursor=400;
修改光標數的限制:
alter system set open_cursors=400 scope = both;
其中scope的取值:both,memory,spfile
memory:表示只更改當前實例,不更改參數文件
spfile:表示只更改參數文件,不更改當前示例,數據庫服務需要重啓
both:表示上邊兩個同時更改
6.帶參數的光標
CURSOR 光標名[(參數名 數據類型[,參數名 數據類型]…)]
IS SELECT 語句;
eg:
--使用帶參數的光標
declare
--定義一個帶參數的遊標
cursor c_emp(dno number) is selectename from emp where deptno=dno;
p_ename emp.ename%type;
begin
--打開遊標時需要參入實參
open c_emp(10);
loop
fetch c_emp into p_ename;
exit when c_emp%notfound;
dbms_output.put_line(p_ename);
end loop;
close c_emp;
end;
/