1.遊標概念sql
在PL/SQL塊中執行SELECT、INSERT、DELETE和UPDATE語句時,ORACLE會在內存中爲其分配上下文區(Context Area),即緩衝區。遊標是指向該區的一個指針,或是一種結構化數據類型。它提供了一種對具備多行數據查詢結果集中的每一行數據分別進行單獨處理的方法,是設計嵌入式SQL語句的應用程序的經常使用編程方式。數據庫
2.遊標使用編程
遊標分爲兩種;oracle
1,隱式遊標ide
2,顯示遊標,oop
A,隱式遊標fetch
隱式遊標是當執行sql語句時自動建立的,當沒有聲明顯示遊標時,程序是沒法控制隱式遊標的。ui
當執行DML語句(insert,update 和 delete)時,隱式遊標就會自動建立,對於insert操做,遊標控制插入的數據,對於delete,update,遊標會記錄影響的行數spa
注意:任何遊標都能訪問 sql%attribute_name .設計
遊標屬性
屬性 |
描述 |
%FOUND |
若是insert,update,delete 執行影響了行數,或者select into 有返回的行數,意思就是有記錄被更新,則返回true,不然返回false. |
%NOTFOUND |
跟上面相反,沒有記錄被更新則返回true,不然返回false. |
%ISOPEN |
對於隱式遊標老是返回false,由於oracle在執行相關的sql語句後會自動關閉。 對於顯示遊標,若是被打開了,就返回true,不然返回false. |
%ROWCOUNT |
返回受影響的行數.當執行Insert,update 或delete語句時,或者是select into 時
|
隱式遊標屬性
屬性 |
值 |
SELECT |
INSERT |
UPDATE |
DELETE |
SQL%ISOPEN |
|
FALSE |
FALSE |
FALSE |
FALSE |
SQL%FOUND |
TRUE |
有結果 |
|
成功 |
成功 |
SQL%FOUND |
FALSE |
沒結果 |
|
失敗 |
失敗 |
SQL%NOTFUOND |
TRUE |
沒結果 |
|
失敗 |
失敗 |
SQL%NOTFOUND |
FALSE |
有結果 |
|
成功 |
失敗 |
SQL%ROWCOUNT |
|
返回行數,只爲1 |
插入的行數 |
修改的行數 |
刪除的行數 |
看例子的前提仍是先準備數據
drop table customer; create table customer ( name varchar(100) primary key, age int, address varchar(100), salary decimal ) delete from customer; insert into customer values ('jack',22,'Singapore',5000.00); insert into customer values ('rose',22,'Japan',2000.00); insert into customer values ('Jet',32,'HongKong',7000.00); insert into customer values ('John',30,'American',5000.00); insert into customer values ('Merry',25,'Singapore',3000.00); insert into customer values ('Peter',26,'China',1000.00); insert into customer values ('Adi',27,'India',2400.00); select * from customer select * from customer where salary <3000
例1;
例1, set serveroutput on; DECLARE total_rows number(2); BEGIN UPDATE customer SET salary = salary + 500 where salary < 3000; IF sql%notfound THEN dbms_output.put_line('no customers selected'); ELSIF sql%found THEN total_rows := sql%rowcount; dbms_output.put_line( total_rows || ' customers selected '); END IF; END; /
結果:
3 customers selected
查看數據會發現,數據庫更新了3條記錄。
大多數時候咱們仍是使用的顯示遊標,這樣更加容易去控制。
B,顯式遊標
遊標的聲明:
CURSOR cursor_name[(parameter[, parameter]…)] [RETURN datatype] IS select_statement;
實用顯示遊標會有如下4個步驟;
CURSOR c1 is select name, salary from customer;
2,打開遊標分配內存
OPEN c1;
3,獲取記錄
FETCH c1 INTO c_name, c_salary;
4,關閉遊標
CLOSE c_1;
下面看一個簡單使用顯示遊標的完整例子
例2;
set serveroutput on; DECLARE c_salary customer.salary%TYPE; c_name customer.name%TYPE; CURSOR c1 is select name,salary from customer; BEGIN open c1; loop fetch c1 into c_name,c_salary; exit when c1%notfound ; dbms_output.put_line(c_name||' '||c_salary); end loop; close c1; END; /
結果;
jack 5000 rose 2500 Jet 7000 John 5000 Merry 3000 Peter 1500 Adi 2900
PL/SQL語言提供了遊標FOR循環語句,自動執行遊標的OPEN、FETCH、CLOSE語句和循環語句的功能;當進入循環時,遊標FOR循環語句自動打開遊標,並提取第一行遊標數據,當程序處理完當前所提取的數據而進入下一次循環時,遊標FOR循環語句自動提取下一行數據供程序處理,當提取完結果集合中的全部數據行後結束循環,並自動關閉遊標。
FOR index_variable IN cursor_name[(value[, value]…)] LOOP -- 遊標數據處理代碼 END LOOP;
用for loop,能夠完成上面例2一樣的效果。
例3;
set serveroutput on; DECLARE c_salary customer.salary%TYPE; c_name customer.name%TYPE; CURSOR c1 is select name,salary from customer; BEGIN for f in c1 loop dbms_output.put_line(f.name||' '||f.salary); end loop; END; /
帶參數的遊標
set serveroutput on; DECLARE c_salary customer.salary%TYPE; c_name customer.name%TYPE; CURSOR c1(p_salary decimal default 3000) is select name,salary from customer where salary >= p_salary; BEGIN --open c1(p_salary=>5000); open c1(5000); loop fetch c1 into c_name,c_salary; exit when c1%notfound ; dbms_output.put_line(c_name||' '||c_salary); end loop; close c1; END;
使用遊標更新和刪除數據(Select for update使用)
遊標修改和刪除操做是指在遊標定位下,修改或刪除表中指定的數據行。這時,要求遊標查詢語句中必須使用FOR UPDATE選項,以便在打開遊標時鎖定遊標結果集合在表中對應數據行的全部列和部分列。
爲了對正在處理(查詢)的行不被另外的用戶改動,ORACLE 提供一個 FOR UPDATE 子句來對所選擇的行進行鎖住。該需求迫使ORACLE鎖定遊標結果集合的行,能夠防止其餘事務處理更新或刪除相同的行,直到您的事務處理提交或回退爲止。
在多表查詢中,使用OF子句來鎖定特定的表,若是忽略了OF子句,那麼全部表中選擇的數據行都將被鎖定。若是這些數據行已經被其餘會話鎖定,那麼正常狀況下ORACLE將等待,直到數據行解鎖。
語法:
SELECT column_list FROM table_list FOR UPDATE [OF column[, column]…] [NOWAIT]
若是另外一個會話已對活動集中的行加了鎖,那麼SELECT FOR UPDATE操做一直等待到其它的會話釋放這些鎖後才繼續本身的操做,對於這種狀況,當加上NOWAIT子句時,若是這些行真的被另外一個會話鎖定,則OPEN當即返回並給出:
ORA-0054 :resource busy and acquire with nowait specified.
例4;
set serveroutput on; DECLARE c_salary customer.salary%TYPE; c_name customer.name%TYPE; CURSOR c1(p_salary customer.salary%TYPE) is select name,salary from customer where salary >= p_salary for update of salary; BEGIN open c1(5000); loop fetch c1 into c_name,c_salary; exit when c1%notfound ; dbms_output.put_line(c_name||' '||c_salary); update customer set salary=salary+100 where current of c1; --更新當前遊標行對應的數據行 end loop; close c1; END; /
這篇就先看到基礎的東西,遊標知識仍是比較多,但願起到拋磚引玉的效果。
這篇文檔比較深刻,供參考
http://www.codeproject.com/Articles/580628/OracleplusPL-fSQLplusCursor