一、 什麼是遊标? 1. 從表中檢索出結果集,從中每次指向一條記錄進行互動的機制
2. 關系資料庫中的操作是在完整的行集合上執行的
由SELECT語句傳回的行集合包括滿足該語句的WHERE子句所列條件的所有行。由該語句傳回完整的行集合叫做結果集
應用程式,尤其是互動和線上應用程式,把完整的結果集作為一個單元處理并不總是有效的 這些應用程式需要一種機制來一次處理一行或連續的幾行。而遊标是對提供這一機制的結果集的擴充
遊标是通過遊标庫來實作的。遊标庫是常常作為資料庫系統或資料通路API的一部分而得以實作的軟體,
用來管理從資料源傳回的資料的屬性(結果集)。這些屬性包括并發管理、在結果集中的位置、傳回的行數,
以及是否能夠在結果集中向前和/或向後移動(可滾動性)。
遊标跟蹤結果集中的位置,并允許對結果集逐行執行多個操作,在這個過程中可能傳回至原始表,也可能不傳回至原始表。
換句話說,遊标從概念上講基于資料庫的表傳回結果集。
由于它訓示結果集中的目前位置 ,就像計算機螢幕上的光标訓示目前位置一樣,“遊标”由此得名。
二、 遊标有什麼作用?
1. 指定結果集中特定行的位置
2. 基于目前的結果集位置檢索一行或連續的幾行
3. 在結果集的目前位置修改行中的資料
4. 對其他使用者所做的資料更改定義不同的敏感性級别
5. 可以以程式設計的方式通路資料庫
三、 為什麼避免使用遊标?
1. 在建立遊标時,最需要考慮的事情是,“是否有辦法避免使用遊标?”
因為遊标的效率較差,如果遊标操作的資料超過1萬行,那麼就應該改寫;
如果使用了遊标,就要盡量避免在遊标循環中再進行表連接配接的操作。
四、 Oracle遊标的類型?
1. 靜态遊标:結果集已經确定(靜态定義)的遊标。分為隐式和顯示遊标
⑴ 隐式遊标: 系統自動定義的遊标,用于處理select into 和DML語句
⑵ 顯示遊标:即使用者自定義遊标,專門用于處理select語句傳回的多行資料 2. REF遊标(動态遊标):動态關聯結果集的臨時對象
靜态遊标指的是程式執行的時候不需要再去解析sql語言,對于sql語句的解析在編譯的時候就可以完成的。 動态遊标由于含有參數,對于sql語句的解析必須要等到參數确定的時候才能完成。 從這個角度來說,靜态遊标的效率也比動态遊标更高一些。
五、 Oracle遊标的狀态有哪些,怎麼使用遊标屬性? 1. 遊标的狀态是通過屬性來表示
%Found :Fetch語句(擷取記錄)執行情況True or False
%NotFound : 最後一條記錄是否提取出True or False
%ISOpen : 遊标是否打開True or False
%RowCount :遊标目前提取的行數
2. 使用遊标的屬性
例子:
Begin
Update emp Set SAL = SAL + 0.1 Where JOB = 'CLERK';
If SQL%Found Then
DBMS_OUTPUT.PUT_LINE('已經更新!');
Else
DBMS_OUTPUT.PUT_LINE('更新失敗!');
End If;
End;
六、 如何使用顯示遊标?如何周遊循環遊标?
1. 使用顯示遊标
⑴ 聲明遊标:劃分存儲區域,注意此時并沒有執行Select 語句。
CURSOR 遊标名(參數 清單) [傳回值類型] IS Select語句;
⑵ 打開遊标:執行Select 語句,獲得結果集存儲到遊标中,此時遊标指向結果集頭, 而不是第一條記錄。
Open 遊标名(參數 清單);
⑶ 擷取記錄:移動遊标取一條記錄
Fetch 遊标名InTo 臨時記錄或屬性類型變量;
⑷ 關閉遊标:将遊标放入緩沖池中,沒有完全釋放資源,可重新打開。
Close 遊标名; 2. 周遊循環遊标
⑴ For循環遊标
循環遊标隐式打開遊标,自動滾動擷取一條記錄,并自動建立臨時記錄類型變量存儲記錄,處理完後自動關閉遊标。
For 變量名 In 遊标名
Loop
資料處理語句;
End Loop;
⑵ Loop循環遊标
...
Loop
Fatch 遊标名InTo 臨時記錄或屬性類型變量;
Exit When 遊标名%NotFound;
End Loop;
... 例子1:
Declare
Cursor myCur is select empno,ename,sal from emp;
vna varchar2(10);
vno number(4);
vsal number(7,2);
Begin
open myCur;
fetch myCur into vno,vna,vsal;
dbms_output.put_line(vno||' '||vna||' '||vsal);
close myCur;
End;
/
例子2:使用loop周遊遊标。
Declare
Cursor myCur is select ename,job,sal,empno from emp;
varE myCur%rowType;
Begin
if myCur%isopen = false then
open myCur;
dbms_output.put_line('Opening...');
end if;
loop
fetch myCur into varE;
exit when myCur%notfound;
dbms_output.put_line(myCur%rowCount||' '||vare.empno||' '||vare.ename||' '||vare.sal);
end loop;
if myCur%isopen then
Close myCur;
dbms_output.put_line('Closing...');
end if;
End;
/
例子3:使用For循環周遊遊标,
Declare
Cursor myCur is select * from emp;
Begin
for varA in myCur
loop
dbms_output.put_line(myCur%rowCount||' '||varA.empno||' '||varA.ename||' '||varA.sal);
end loop;
End;
/
七、 怎樣更新和删除顯示遊标中的記錄?
1. UPDATE或DELETE語句中的WHERE CURRENT OF子串專門處理要執行UPDATE或DELETE操作的表中取出的最近的資料。
要使用這個方法,在聲明遊标時必須使用FOR UPDATE子串,當對話使用FOR UPDATE子串打開一個遊标時,
所有傳回集中的資料行都将處于行級(ROW-LEVEL)獨占式鎖定,其他對象隻能查詢這些資料行,
不能進行UPDATE、DELETE或SELECT...FOR UPDATE操作。
在多表查詢中,使用OF子句來鎖定特定的表,如果忽略了OF子句,那麼所有表中選擇的資料行都将被鎖定。
如果這些資料行已經被其他會話鎖定,那麼正常情況下ORACLE将等待,直到資料行解鎖。
2. 使用更新或删除:
⑴ 聲明更新或删除顯示遊标:
Cursor 遊标名 IS SELECT語句 For Update [ Of 更新列列名];
Cursor 遊标名 IS SELECT語句 For Delete [ Of 更新列列名];
⑵ 使用顯示遊标目前記錄來更新或删除:
Update 表名 SET 更新語句 Where Current Of 遊标名; Delete From 表名 Where Current Of 遊标名;
例子1:更新顯示遊标記錄
Declare
Cursor myCur is select job from emp for update;
vjob empa.job%type;
rsal empa.sal%type;
Begin
open myCur;
loop
fetch myCur into vjob;
exit when myCur%notFound;
case (vjob)
when 'ANALYST' then rsal := 0.1;
when 'CLERK' then rsal := 0.2;
when 'MANAGER' then rsal := 0.3;
else
rsal := 0.5;
end case;
update emp set sal = sal + rsal where current of myCur;
end loop;
End;
/
例子2:删除顯示遊标記錄
Declare
Cursor MyCursor Select JOB From empa For Update;
vSal emp.Sal%TYPE;
Begin
Loop
Fetch MyCursor InTo vSal;
Exit When MyCursor%NotFound;
If vSal < 800 Then
Delete From empa Where Cursor Of MyCursor;
End If;
End Loop;
End;/
八、 什麼是帶參數的顯示遊标?
1. 與過程和函數相似,可以将參數傳遞給遊标并在查詢中使用。
參數隻定義資料類型,沒有大小(所有Oracle中的形參隻定義資料類型,不指定大小)。
與過程不同的是,遊标隻能接受傳遞的值,而不能傳回值。
可以給參數設定一個預設值,當沒有參數值傳遞給遊标時,就使用預設值。
遊标中定義的參數隻是一個占位符,在别處引用該參數不一定可靠。 2. 使用帶參數的顯示遊标
⑴ 聲明帶參數的顯示遊标:
CURSOR 遊标名 [(parameter[,parameter],...)] IS Select語句;
參數形式: 1. 參數名 資料類型 2. 參數名 資料類型 DEFAULT 預設值
例子:
Declare
Cursor MyCursor(pSal Number Default 800) Select JOB From empa Where SAL > pSal ;
varA MyCursor%ROWTYPE;
Begin
Loop
Fetch MyCursor InTo varA;
Exit When MyCursor%NotFound;
DBMS_OUTPUT.PUT_LINE(MyCursor%RowCount||' '||varA.empno||' '||varA.ename||' '||varA.sal);
End Loop;
End;/
REF CURSOR(動态遊标)
一、 什麼是REF遊标 ? 動态關聯結果集的臨時對象。即在運作的時候動态決定執行查詢。
二、 REF遊标有什麼作用?
實作在程式間傳遞結果集的功能,利用REF CURSOR也可以實作BULK SQL,進而提高SQL性能。
三、 靜态遊标和REF遊标的差別是什麼?
1. 靜态遊标是靜态定義,REF遊标是動态關聯
2. 使用REF遊标需REF遊标變量
3. REF遊标能做為參數進行傳遞,而靜态遊标是不可能的
四、 什麼是REF遊标變量?
REF遊标變量是一種引用REF遊标類型的變量,指向動态關聯的結果集。
五、 怎麼使用REF遊标 ?
1. 聲明REF 遊标類型,确定REF 遊标類型
⑴ 強類型REF遊标:指定retrun type,REF 遊标變量的類型必須和return type一緻。
文法:Type REF遊标名 IS Ref Cursor Return 結果集傳回記錄類型;
⑵ 弱類型REF遊标:不指定return type,能和任何類型的CURSOR變量比對,用于擷取任何結果集。
文法:Type REF遊标名 IS Ref Cursor;
2. 聲明Ref遊标類型變量
文法:變量名 已聲明Ref遊标類型;
3. 打開REF遊标,關聯結果集
文法:Open Ref遊标類型變量 For 查詢語句傳回結果集;
4. 擷取記錄,操作記錄
文法:Fatch REF遊标名 InTo 臨時記錄類型變量或屬性類型變量清單;
5. 關閉遊标,完全釋放資源
文法:Close REF遊标名;
例子:強類型REF遊标
Declare
Type MyRefCurA IS REF CURSOR RETURN emp%RowType;
Type MyRefCurB IS REF CURSOR RETURN emp.ename%Type;
vRefCurA MyRefCurA;
vRefCurB MyRefCurB;
vTempA vRefCurA%RowType;
vTempB vRefCurB.ename%Type;
Begin
Open vRefCurA For Select * from emp Where SAL > 2000;
Loop
Fatch vRefCurA InTo vTempA;
Exit When vRefCurA%NotFound;
DBMS_OUTPUT.PUT_LINE(vRefCurA%RowCount||' '|| vTempA.eno||' '||vTempA.ename ||' '||vTempA.sal)
End Loop;
Close vRefCurA;
DBMS_OUTPUT.PUT_LINE('--------------------------------------------------------------');
Open vRefCurB For Select ename from emp Where SAL > 2000;
Loop
Fatch vRefCurB InTo vTempB;
Exit When vRefCurB%NotFound;
DBMS_OUTPUT.PUT_LINE(vRefCurB%RowCount||' '||vTempB)
End Loop;
Close vRefCurB;
DBMS_OUTPUT.PUT_LINE('----------------------------------------------------------------');
Open vRefCurA For Select * from emp Where JOB = 'CLERK';
Loop
Fatch vRefCurA InTo vTempA;
Exit When vRefCurA%NotFound;
DBMS_OUTPUT.PUT_LINE(vRefCurA%RowCount||' '|| vTempA.eno||' '||vTempA.ename ||' '||vTempA.sal)
End Loop;
Close vRefCurA; End;
例子:弱類型REF遊标
Declare
Type MyRefCur IS Ref Cursor;
vRefCur MyRefCur;
vtemp vRefCur%RowType;
Begin
Case(&n)
When 1 Then Open vRefCur For Select * from emp;
When 2 Then Open vRefCur For Select * from dept;
Else
Open vRefCur For Select eno, ename from emp Where JOB = 'CLERK';
End Case;
Close vRefCur;
End;