Oracle 引數 遊標[遊標更新刪除資料]
一、引數遊標
引數遊標是帶有引數的遊標,在定義引數遊標之後,當使用不同引數值多次開啟遊標時,可以產生不同的結果集,語法如下:
cursor cursor_name(parameter_name datatype) is select_statement;
定義引數遊標時,遊標引數只能指定資料型別,而不能指定長度。
示例如下:
Oracle程式碼
1.declare
2.cursor temp_cursor(no number) is select name from cip_temps where id=no;
3.v_name cip_temps.name%type;
4.begin
5.open temp_cursor(1);
6.loop
7.fetch temp_cursor into v_name;
8.exit when temp_cursor%notfound;
9.dbms_output.put_line(v_name);
10.end loop;
11.close temp_cursor;
12.end;
declare
cursor temp_cursor(no number) is select name from cip_temps where id=no;
v_name cip_temps.name%type;
begin
open temp_cursor(1);
loop
fetch temp_cursor into v_name;
exit when temp_cursor%notfound;
dbms_output.put_line(v_name);
end loop;
close temp_cursor;
end;
二、使用遊標更新或刪除資料
通過使用顯示遊標,不僅可以一行一行的處理select語句結果,而且也可以更新或刪除當前遊標的資料,注意,如果要通過遊標更新或刪除資料,在定義遊標時一定要帶有for update子句,語法如下:
cursor cursor_name(parameter_name datatype) is select_statement for updae [of column_reference][nowait];如上所示:for update子句用於在遊標結果集資料上加行共享鎖,以防止其他使用者在相應行上執行DML操作,當select語句要引用到多張表是,使用of子句可以確定哪些表要加鎖,如果沒有of子句,則會在select語句所引用的全部表上加鎖,nowait用於指定不等待鎖,為了更新或刪除當前遊標行資料,必須在update 或delete語句中引用where current of 子句,語法如下:
update table_name set column=.. where current of cursor_name;
delete from table_name where current of cursor_name;
1、使用遊標更新資料
Oracle程式碼
1.declare
2.cursor temp_cursor is select name,address,id from cip_temps for update;
3.v_name cip_temps.name%type;
4.v_address cip_temps.ADDRESS%type;
5.v_id cip_temps.id%type;
6.begin
7.open temp_cursor;
8.loop
9.fetch temp_cursor into v_name,v_address,v_id;
10.exit when temp_cursor%NOTFOUND;
11.if(v_id>4) then
12.update cip_temps set name='name'||to_char(v_id),address='address'||to_char(v_id) where current of temp_cursor;
13.end if;
14.end loop;
15.close temp_cursor;
16.end;
declare
cursor temp_cursor is select name,address,id from cip_temps for update;
v_name cip_temps.name%type;
v_address cip_temps.ADDRESS%type;
v_id cip_temps.id%type;
begin
open temp_cursor;
loop
fetch temp_cursor into v_name,v_address,v_id;
exit when temp_cursor%NOTFOUND;
if(v_id>4) then
update cip_temps set name='name'||to_char(v_id),address='address'||to_char(v_id) where current of temp_cursor;
end if;
end loop;
close temp_cursor;
end;
2、使用遊標刪除資料
Oracle程式碼
1.declare
2.cursor temp_cursor is select name,address,id from cip_temps for update;
3.v_name cip_temps.name%type;
4.v_address cip_temps.ADDRESS%type;
5.v_id cip_temps.id%type;
6.begin
7.open temp_cursor;
8.loop
9.fetch temp_cursor into v_name,v_address,v_id;
10.exit when temp_cursor%NOTFOUND;
11.if(v_id>2) then
12.delete from cip_temps where current of temp_cursor;
13.end if;
14.end loop;
15.close temp_cursor;
16.end;
declare
cursor temp_cursor is select name,address,id from cip_temps for update;
v_name cip_temps.name%type;
v_address cip_temps.ADDRESS%type;
v_id cip_temps.id%type;
begin
open temp_cursor;
loop
fetch temp_cursor into v_name,v_address,v_id;
exit when temp_cursor%NOTFOUND;
if(v_id>2) then
delete from cip_temps where current of temp_cursor;
end if;
end loop;
close temp_cursor;
end;
3、使用of子句在特定表加行共享鎖。
如果使用子查詢涉及到多張表,那麼預設情況下會在所有表上加行共享鎖,為了只在特定表上加行共享鎖,需要在for update子句後帶有of子句,of後面跟欄位名,如果跟表名或遊標名稱,則會報錯:標示符無效。示例如下:
Oracle程式碼
1.declare
2.cursor gData is select name,address,cip_temps.id from cip_temps,cip_t
3.where cip_temps.id=cip_t.id for update of address;
4.rs gData%rowtype;
5.begin
6. open gData;
7. loop
8. fetch gData into rs;
9. exit when gData%notfound;
10. if rs.id=1 then
11. delete from cip_temps where current of gData;
12. else
13. update cip_temps set name='塞北的雪' where current of gData;
14. end if;
15.
16. end loop;
17. close gData;
18.end;
declare
cursor gData is select name,address,cip_temps.id from cip_temps,cip_t
where cip_temps.id=cip_t.id for update of address;
rs gData%rowtype;
begin
open gData;
loop
fetch gData into rs;
exit when gData%notfound;
if rs.id=1 then
delete from cip_temps where current of gData;
else
update cip_temps set name='塞北的雪' where current of gData;
end if;
end loop;
close gData;
end;
4、使用nowait子句
使用for update語句對被作用於行加鎖,如果其他會話已經在被作用於行上加鎖,那麼預設情況下當前會話要一直等待對方釋放鎖,通過在for update子句中指定 nowait語句,可以避免等待鎖,當指定了nowait子句之後,如果其他會話已經在被作用行加鎖,那麼當前會話會顯示錯誤提示資訊,並退出PL/SQL,示例如下:
Oracle程式碼
1.declare
2.cursor gData is select name,address,cip_temps.id from cip_temps,cip_t
3.where cip_temps.id=cip_t.id for update nowait;
4.rs gData%rowtype;
5.begin
6. open gData;
7. loop
8. fetch gData into rs;
9. exit when gData%notfound;
10. if rs.id=1 then
11. delete from cip_temps where current of gData;
12. else
13. update cip_temps set name='塞北的雪' where current of gData;
14. end if;
15.
16. end loop;
17. close gData;
18.end;
declare
cursor gData is select name,address,cip_temps.id from cip_temps,cip_t
where cip_temps.id=cip_t.id for update nowait;
rs gData%rowtype;
begin
open gData;
loop
fetch gData into rs;
exit when gData%notfound;
if rs.id=1 then
delete from cip_temps where current of gData;
else
update cip_temps set name='塞北的雪' where current of gData;
end if;
end loop;
close gData;
end;
三、遊標for迴圈
使用遊標for迴圈是循環遊標最簡單的方法,oracle會隱含開啟遊標、迴圈提取資料、關閉遊標,語法如下:
for record_name in cursor_name loop
..........
end loop;
如上所示:cursor_name是已經定義的遊標名稱,record_name是oracle隱含定義的記錄變數。
1、使用遊標for迴圈
當使用遊標開發程式時,建議使用for迴圈,從而簡化程式碼程式,示例如下:
Oracle程式碼
1.declare
2.cursor temp_cursor is select name,age,address,id from cip_temps;
3.begin
4.for emp_record in temp_cursor loop
5.dbms_output.put_line(temp_cursor%rowcount||'第一行資料:'||emp_record.name||':'|| emp_record.age||':'|| emp_record.address||':'|| emp_record.id);
6.end loop;
7.end;
declare
cursor temp_cursor is select name,age,address,id from cip_temps;
begin
for emp_record in temp_cursor loop
dbms_output.put_line(temp_cursor%rowcount||'第一行資料:'||emp_record.name||':'|| emp_record.age||':'|| emp_record.address||':'|| emp_record.id);
end loop;
end;
2、在遊標for迴圈時直接使用子查詢
Sql程式碼
1.declare
2.begin
3.for emp_record in (select * from cip_temps) loop
4.dbms_output.put_line('第一行資料:'||emp_record.name||':'|| emp_record.age||':'|| emp_record.address||':'|| emp_record.id);
5.end loop;
6.end;