Decode360's Blog

          業精于勤而荒于嬉 QQ:150355677 MSN:decode360@hotmail.com

            BlogJava :: 首頁 :: 新隨筆 :: 聯系 ::  :: 管理 ::
            397 隨筆 :: 33 文章 :: 29 評論 :: 0 Trackbacks
          Cursor的基本使用方法

          ?

          ??? 今天在用到Cursor的時候發現,有很多游標相關的知識還是有欠缺,在網上搜了篇基礎講解的文,覺得還不錯,自己整理了一下發上來。雖然很基礎,但是有一些內容之前確實沒有很扎實得掌握,所以記下來也可以加深一下印象。

          ?

          一、Cursor的分類

          ?

          ??? Cursor

          ?

          ?

          二、各類Cursor舉例

          ?

          ---- 靜態游標 - 顯式游標

          set serveroutput on

          declare

          ? cursor emp_sor(emp_deptno in number ) is

          ??? select * from emp where deptno=emp_deptno ;

          ? emp_i emp% rowtype ;

          begin

          ? dbms_output.put_line( 'Getting emp from deptno 10' );

          ? open emp_sor( 10 );

          ? loop

          ??? fetch emp_sor into emp_i;

          ??? exit when emp_sor% notfound ;

          ??? dbms_output.put_line( 'Employee id ' ||emp_i.empno|| ' is:' );

          ??? dbms_output.put_line(emp_i.ename);

          ? end loop ;

          ? close emp_sor;

          end ;

          /

          ?

          ---- 靜態游標 - 隱式游標 -1.DML

          begin

          ? update emp set ename=ename ; --where 1=2;

          ?dbms_output.put_line( 'update ' || sql % rowcount || ' records' );

          end ;

          /

          ?

          ---- 靜態游標 - 隱式游標 -2.loop for

          begin

          ? for r_sor in ( select empno,ename from emp)

          ? loop

          ?? dbms_output.put_line(r_sor.empno || ' : ' || r_sor.ename);

          ? end loop ;

          end ;

          /

          ?

          ---- 靜態游標 - 隱式游標 -3.select into

          declare

          ? v? varchar2 ( 20 );

          begin

          ? select ename into v from emp

          ? where rownum = 1 ;

          ? dbms_output.put_line(v);

          ? dbms_output.put_line( sql % rowcount );

          end ;

          /

          ?

          ---- 動態游標 - 弱類型

          Declare

          ? type rc is ref cursor ;

          ? cursor c is select * from dual;

          ? l_cursor rc;

          begin

          ? if (to_char( sysdate , 'dd' ) = 30 ) then

          ???? open l_cursor for 'select * from emp' ;-- ref cursor with dynamic sql

          ? elsif (to_char( sysdate , 'dd' ) = 29 ) then

          ???? open l_cursor for select * from dept;-- ref cursor with static sql

          ? else

          ???? open l_cursor for select * from dual;-- with ref cursor with static sql

          ? end if ;

          ? open c;-- the "normal" static cursor

          end ;

          /

          ?

          ---- 動態游標 - 強類型

          declare

          ? type emp_job is record (empno number ,

          ???????????????????????? ename varchar2 ( 20 ),

          ???????????????????????? job?? varchar2 ( 30 )

          ???????????????????????? );

          ? type emp_refcur is ref cursor return emp_job; -- 聲明 REF CURSOR

          ? emp_sor emp_refcur;

          ? emp_i?? emp_job;

          begin

          ? open emp_sor for

          ??? select empno,ename,job from emp where rownum < 10 order by 1 ;

          ? loop

          ??? fetch emp_sor into emp_i;

          ? exit when emp_sor% notfound ;

          ??? dbms_output.put_line(emp_i.ename || '''s job is :' );

          ??? dbms_output.put_line(emp_i.job);

          ? end loop ;

          ? close emp_sor;

          end ;

          /

          ?

          ?

          普通cursor與REF cursor的區別:

          ?

          1)靜態cursor不能返回到客戶端,只有PL/SQL才能利用它。ref cursor能夠被返回到客戶端,這就是從Oracle的存儲過程返回結果集的方式。

          2)靜態cursor可以是全局的,而ref cursor則不是。

          3)ref cursor可以從子例程傳遞到子例程,而cursor則不能。為了共享靜態cursor,必須在包說明或包體中把它定義為全局cursor。

          ?? 因為使用全局變量通常不是一種很好的編碼習慣,因此可以用ref cursor來共享PL/SQL中的cursor,無需混合使用全局變量。

          4)使用靜態cursor,通過靜態SQL(但不用ref cursor),比使用ref cursor效率高,而ref cursor的使用僅限于以下幾種情況:

          ??? 1.把結果集返回給客戶端;
          ??? 2.在多個子例程之間共享cursor(實際上與上面提到的一點非常類似);
          ??? 3.沒有其他有效的方法來達到你的目標時,則使用ref cursor,正如必須用動態SQL時那樣

          ?

          ---- 動態游標 -sys_refcursor

          DECLARE

          ? TYPE mytable IS TABLE OF emp% ROWTYPE ;

          ? l_data mytable;

          ? l_refc sys_refcursor ;

          BEGIN

          ? OPEN l_refc FOR

          ? SELECT empno,ename,job,mgr,hiredate,sal,comm,deptno FROM emp;

          ? FETCH l_refc BULK COLLECT INTO l_data;

          ? CLOSE l_refc;

          ? FOR i IN 1 .. l_data.COUNT

          ? LOOP

          ??? DBMS_OUTPUT.put_line ( l_data(i).ename || ' was hired since ' || l_data (i).hiredate );

          ? END LOOP ;

          END ;

          ?

          非強類型的Ref cursor 和sys_refcursor的區別:

          A REF CURSOR that does not specify the return type such as SYS_REFCURSOR. Meaning the SYS_REFCURSOR can be opened for a dynamic SQL query, where as simple REF CURSOR can not be opened for a query dynamically built at execution time.

          ?

          ?

          三、游標屬性

          ?

          /*************************************************************

          游標屬性:

          %FOUND :變量最后從游標中獲取記錄的時候,在結果集中找到了記錄。

          %NOTFOUND :變量最后從游標中獲取記錄的時候,在結果集中沒有找到記錄。

          %ROWCOUNT :當前時刻已經從游標中獲取的記錄數量。

          %ISOPEN :是否打開。

          **************************************************************/

          ?

          ---- 靜態游標 - 游標屬性

          Declare

          ? Cursor emp_sor is

          ? Select * from emp where rownum< 6 order by 1 ;

          ? emp_i emp% rowtype ;

          ? num number := 1 ;

          Begin

          ? Open emp_sor;

          ? Fetch emp_sor into emp_i;

          ? Loop

          ??? If emp_sor% found then

          ????? Dbms_output.put_line( 'Looping over record ' ||num|| ' of ' || emp_sor% rowcount );

          ????? Fetch emp_sor into emp_i;

          ? ???? num := num + 1 ;

          ??? Elsif emp_sor% notfound then

          ????? Exit ;? ---exit loop, not IF

          ??? End if ;

          ? End loop ;

          ?

          ? If emp_sor% isopen then

          ??? Close emp_sor;

          ? End if ;

          End ;

          /

          ?

          posted on 2008-08-29 22:43 decode360 閱讀(475) 評論(0)  編輯  收藏 所屬分類: 06.PLSQL
          主站蜘蛛池模板: 北安市| 伊春市| 松阳县| 遵化市| 新竹市| 石嘴山市| 伊宁市| 响水县| 得荣县| 公主岭市| 宁津县| 自治县| 且末县| 陵水| 贡觉县| 江孜县| 韶山市| 顺昌县| 龙胜| 忻城县| 金门县| 嵊泗县| 康乐县| 息烽县| 云阳县| 宁河县| 醴陵市| 娱乐| 秭归县| 马关县| 高唐县| 武定县| 松桃| 天长市| 巴塘县| 华坪县| 深泽县| 禄劝| 科尔| 陆良县| 宜宾市|