在網(wǎng)絡(luò)或者書籍中,我們可以非常容易的了解到ORACLE中游標(biāo)的生命周期包括如下部分:
1,打開游標(biāo)-- open cursor,此步驟在 UGA 里申請一塊內(nèi)存給游標(biāo)使用,這個時候游標(biāo)還沒有與sql語句關(guān)聯(lián)。
2,解析游標(biāo)-- sql與游標(biāo)關(guān)聯(lián)起來,解析sql的內(nèi)容(包括執(zhí)行計劃),解析后的內(nèi)容會被加載到共享池中(share pool-- library cache)。在UGA申請的內(nèi)存用來保存指向這個共享游標(biāo)(share cursor)在library cache中的位置。
3,定義輸出變量-- 如果sql語句返回數(shù)據(jù),必須先定義接收數(shù)據(jù)的變量。這一點不僅對查詢語句很重要,對于使用returning 自居的delete、insert和update 語句也很重要。
4,綁定輸入變量-- 如果sql語句使用了綁定變量,必須提供他們的值。綁定的過程是不做什么檢查。如果指定了無效的數(shù)據(jù),執(zhí)行的過程中會爆出一個運行時錯誤。
5,執(zhí)行游標(biāo)-- 執(zhí)行跟游標(biāo)關(guān)聯(lián)的sql。注意 數(shù)據(jù)庫并非總是在這一步做重要的事情。事實上,對于很多類型的查詢語句來說,真正的處理過程通常會被推遲到fetch數(shù)據(jù)階段。
6,獲取游標(biāo)-- 如果sql語句返回數(shù)據(jù),這一步會接受這些數(shù)據(jù)。特別是在查詢語句中,大部分的處理工作都是在這一步進行的。在查詢語句中,可能只會讀取部分記錄,換句話講,游標(biāo)有可能在取到所有記錄前被關(guān)閉。
7,關(guān)閉游標(biāo)-- 釋放UGA中與這個游標(biāo)有關(guān)的資源,從而這些資源可供其他的游標(biāo)使用。在library cache中的share cursor不會被清除,它會繼續(xù)保留在library cache 中,等待被重用(軟解析重用)。
重復(fù)的內(nèi)容,我們不做過多介紹,今天我們來看一下游標(biāo)生命周期中各個部分所扮演的角色,以及如何利用它們來優(yōu)化我們的程序。
借鑒《oracle性能診斷藝術(shù)》中的代碼片段,我們來研究一下游標(biāo)的生命周期;
? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 create or replace procedure cursor_test as l_ename emp.ename%TYPE := 'SCOTT'; l_empno dbms_sql.Number_Table; l_cursor INTEGER; l_retval INTEGER; cnt integer := 1; indx integer := 1; res varchar2(4000); BEGIN for i in 1 .. 1000 loop l_cursor := DBMS_SQL.open_cursor; DBMS_SQL.parse(l_cursor, 'select empno from emp where ename <> :ename and 0 <> '||i , DBMS_SQL.native); l_empno.delete(); DBMS_SQL.define_array(l_cursor, 1, l_empno,cnt,indx); DBMS_SQL.bind_variable(l_cursor, ':ename', to_char(i)); l_retval := DBMS_SQL.execute(l_cursor); while DBMS_SQL.fetch_rows(l_cursor) > 0 loop dbms_sql.column_value(l_cursor, 1, l_empno); end loop; res :=''; for j in 1 .. l_empno.count() loop res := res || L_EMPNO(j); end loop; DBMS_OUTPUT.PUT_LINE(res); dbms_sql.close_cursor(l_cursor); end loop; end;新聞熱點
疑難解答
圖片精選