?游標(cursor )是一個私有的SQL工作區域,是一個指向上下文區的句柄或指針,位于內存中的 "臨時表" 。 ?游標是SQL的一個內存工作區,由系統或用戶以變量的形式定義。游標的作用就是用于臨時存儲從數據庫中提取的數據塊。在某些情況下,需要把數據從存放在磁盤的表中調到計算機內存中進行處理,最后將處理結果顯示出來或最終寫回數據庫。這樣數據處理的速度才會提高,否則頻繁的磁盤數據交換會降低效率 游標用來管理從數據源返回的數據的屬性(結果集)。這些屬性包括并發管理、在結果集中的位置、返回的行數,以及是否能夠在結果集中向前和/或向后移動(可滾動性)。 游標跟蹤結果集中的位置,并允許對結果集逐行執行多個操作,在這個過程中可能返回至原始表,也可能不返回至原始表 ?  |
原理 | 游標是從數據表中提取出來的數據,以?臨時表?的形式存放到?內存中 ,在游標中有一個?數據指針,?在初始狀態下指向的是首記錄,利用?fetch ?語句可以移動該指針,從而對游標中的數據進行各種操作,然后將操作結果寫回到數據庫中。 |
作用 | 1、用來查詢數據庫,獲取記錄集合(結果集)的指針,可以讓開發者基于當前的結果集位置檢索一行或連續的幾行在每 ? ? 條結果集上作操作,以編 程的方式訪問數據。 2、用 ‘犧牲內存’ 來提升 SQL 執行效率,適用于?大數據處理。 3.在結果集的當前位置修改行中的數據,對其他用戶所做的數據更改定義不同的敏感性級別。 ? 程序語言是面向記錄的,一組變量一次只能存放一個變量或者一條記錄,無法直接接收數據庫中的查詢結果集引入游標就解決了這個問題 |
游 標的類型 |  REF 游標用于處理運行時才能確定的動態 SQL 查詢的結果 隱式游標不易被用戶和程序員察覺和意識到,實際上Oracle服務器使用隱式游標來解析和執行我們提交的SQL 語句;而顯式游標是程序員在程序中顯式聲明的;通常我們說的游標均指顯式游標 |
隱式 游標 | 在 PL/SQL 中使用?DML 和 select into 時,會自動創建隱式游標,隱式游標自動聲明、打開和關閉(無法手動查看 ),其名為?SQL,通過檢查隱式游標的屬性可以獲得?最近 執行的 DML 和 select into 語句的信息 DML操作和單行SELECT語句會使用隱式游標,它們是:? * 插入操作:INSERT。? * 更新操作:UPDATE。? * 刪除操作:DELETE。? * 單行查詢操作:SELECT ... INTO ...。 |
當系統使用一個隱式游標時,可以通過隱式游標的屬性來了解操作的狀態和結果,進而控制程序的流程。隱式游標可以使用名字SQL來訪問,但要注意,通過SQL游標名總是只能訪問前一個DML操作或單行SELECT操作的游標屬性。所以通常在剛剛執行完操作之后,立即使用SQL游標名來訪問屬性 %FOUND | 語句影響了一行或多行時為 TRUE,前一個 fetch 語句是否有值 ,true:有,false:沒有 | %NOTFOUND | 語句沒有影響任何行時為TRUE,與上述相反,常被用于?退出循環 ,true:有,false:沒有, null : 空。注意哦,只有 為 true 時,才退出(當 第一次 fetch 為 null 時,不會退出!) EXIT WHEN SQL%NOTFOUND OR SQL%NOTFOUND IS NULL; | %ROWCOUNT | 語句影響的行數,當前成功執行的數據行數(非總記錄數 ) | %ISOPEN | 游標是否打開,始終為FALSE |
SQL> DECLAREv_TOYID TOYS.ID%type := '&TOYID';v_TOYNAME TOYS.NAME%Type := '&TOYNAME';BEGINUPDATE TOYS SET NAME = v_TOYNAMEWHERE toyid=v_TOYID;IF SQL%NOTFOUND THENDBMS_OUTPUT.PUT_LINE('編號未找到。');ELSEDBMS_OUTPUT.PUT_LINE(‘表已更新');END IF;END;
DECLAREv_RoomData rooms%ROWTYPE;
BEGINSELECT *INTO v_RoomData FROM rooms WHERE room_id = -1;IF SQL%NOTFOUND THEN
/*注意,這里不執行,以上自動引發select into預定義異常*/INSERT INTO temp_table (char_col) VALUES
('Not found!');END IF;
EXCEPTIONWHEN NO_DATA_FOUND THEN
/*注意,這是真正執行的*/INSERT INTO temp_table (char_col)VALUES ('Not found, exception handler');
END;
declare2 v_rows number;3 begin4 update emp5 set comm=10006 where deptno=30;7 v_rows:=SQL%ROWCOUNT;8 dbms_output.put_line('給部門30的'
|| v_rows || '個雇員每人加了1000元獎金');9 end; ? |
顯式游標 | 顯式游標在 PL/SQL 塊的聲明部分定義查詢,該查詢可以返回多行 1、一行一行的處理返回的數據。 2、保持當前處理行的一個跟蹤,像一個指針一樣指示當前的處理的記錄。 3、允許程序員在PLSQL塊中人為的控制游標的開啟、關閉、上下移動 |
 聲明游標 | 劃分存儲區域,注意此時并沒有執行Select?語句 ? CURSOR 游標名[(參數1 數據類型[,參數2 數據類型...])]? IS SELECT語句;? 參數是可選部分,所定義的參數可以出現在SELECT語句的WHERE子句中。如果定義了參數,則必須在打開游標時傳遞相應的實際參數。? SELECT語句是對表或視圖的查詢語句,甚至也可以是聯合查詢。可以帶WHERE條件、ORDER BY或GROUP BY等子句,但不能使用INTO子句。在SELECT語句中可以使用在定義游標之前定義的變量。? | 打開游標 | 執行Select?語句,獲得結果集存儲到游標中,此時游標指向結果集頭, 而不是第一條記錄 在可執行部分,按以下格式打開游標:? OPEN 游標名[(實際參數1[,實際參數2...])];? 打開游標時,SELECT語句的查詢結果就被傳送到了游標工作區。 | 結果集控制 | 移動游標取一條記錄 在可執行部分,按以下格式將游標工作區中的數據取到變量中。提取操作必須在打開游標之后進行。? FETCH 游標名 INTO 變量名1[,變量名2...];? 或? FETCH 游標名 INTO 記錄變量;? 游標打開后有一個指針指向數據區,FETCH語句一次返回指針所指的一行數據,要返回多行需重復執行,可以使用循環語句來實現。控制循環可以通過判斷游標的屬性來進行。? 下面對這兩種格式進行說明:? 第一種格式中的變量名是用來從游標中接收數據的變量,需要事先定義。變量的個數和類型應與SELECT語句中的字段變量的個數和類型一致。? 第二種格式一次將一行數據取到記錄變量中,需要使用%ROWTYPE事先定義記錄變量,這種形式使用起來比較方便,不必分別定義和使用多個變量。? 定義記錄變量的方法如下:? 變量名 表名|游標名%ROWTYPE;? 其中的表必須存在,游標名也必須先定義。 | 關閉游標 | 顯式游標打開后,必須顯式地關閉。游標一旦關閉,游標占用的資源就被釋放,游標變成無效,必須重新打開才能使用。 |
SQL>DECLAREmy_toy_price toys.toyprice%TYPE; 聲明游標CURSOR toy_cur ISSELECT toyprice FROM toysWHERE toyprice<250;BEGINOPEN toy_cur; LOOPFETCH toy_cur INTO my_toy_price;EXIT WHEN toy_cur%NOTFOUND;DBMS_OUTPUT.PUT_LINE ('TOYPRICE=:玩具單價=:'||my_toy_price);END LOOP;CLOSE toy_cur;END;
帶參數的 DECLAREdesig VARCHAR2(20);emp_code VARCHAR2(5);empnm VARCHAR2(20);CURSOR emp_cur(desigparam VARCHAR2) ISSELECT empno, ename FROM employeeWHERE designation=desig;BEGINdesig:= '&desig';OPEN emp_cur(desig);LOOPFETCH emp_cur INTO emp_code,empnm;EXIT WHEN emp_cur%NOTFOUND;DBMS_OUTPUT.PUT_LINE(emp_code||' '||empnm);END LOOP;CLOSE emp_cur;END ?允許使用游標刪除或更新活動集中的行 聲明游標時必須使用 SELECT … FOR UPDATE語句 所有返回集中的數據行都將處于行級(ROW-LEVEL)獨占式鎖定,其他對象只能查詢這些數據行, ??不能進行UPDATE、DELETE或SELECT...FOR UPDATE操作。 ???在多表查詢中,使用OF子句來鎖定特定的表,如果忽略了OF子句,那么所有表中選擇的數據行都將被鎖定。 ???如果這些數據行已經被其他會話鎖定,那么正常情況下ORACLE將等待,直到數據行解鎖 SQL> SET SERVEROUTPUT ON
SQL> DECLAREnew_price NUMBER;CURSOR cur_toy ISSELECT toyprice FROM toys WHERE toyprice<100FOR UPDATE OF toyprice;
BEGINOPEN cur_toy;LOOPFETCH cur_toy INTO new_price;EXIT WHEN cur_toy%NOTFOUND;UPDATE toysSET toyprice = 1.1*new_priceWHERE CURRENT OF cur_toy;END LOOP;CLOSE cur_toy;COMMIT;
END;
declare2 cursor mycur(dept_no integer) is3 select * from dept4 where deptno>dept_no for update;5 begin6 for myreco in mycur(50) loop7 delete from dept8 where current of mycur;9 end loop;10 end; 循環游標 declare2 cursor c_dept is3 select deptno, dname from dept order by deptno;4 cursor c_emp(p_dept varchar2) is5 select ename,sal from emp where deptno=p_dept order by ename;6 v_salary emp.sal%type;7 begin8 for r_dept in c_dept loop9 dbms_output.put_line('Department:' || r_dept.deptno||'-'||r_dept.dname);10 v_salary:=0;11 for r_emp in c_emp(r_dept.deptno) loop12 dbms_output.put_line('Name:'|| r_emp.ename||' salary='||r_emp.sal);13 v_salary:=v_salary+r_emp.sal;14 end loop;15 dbms_output.put_line('total salary for dept:'|| v_salary);16 end loop;17* end; ? |
動態SELECT | Oracle支持動態SELECT語句和動態游標,動態的方法大大擴展了程序設計的能力。? 對于查詢結果為一行的SELECT語句,可以用動態生成查詢語句字符串的方法,在程序執行階段臨時地生成并執行,語法是:? execute immediate 查詢語句字符串 into 變量1[,變量2...];? SET SERVEROUTPUT ON DECLARE str varchar2(100); v_ename varchar2(10); begin str:='select ename from scott.emp where empno=7788'; execute immediate str into v_ename; dbms_output.put_line(v_ename); END; ? |
REF 游標 | 在變量聲明部分定義的游標是靜態的,不能在程序運行過程中修改。雖然可以通過參數傳遞來取得不同的數據,但還是有很大的局限性。通過采用動態游標,可以在程序運行階段隨時生成一個查詢語句作為游標。要使用動態游標需要先定義一個游標類型,然后聲明一個游標變量,游標對應的查詢語句可以在程序的執行過程中動態地說明。 ? REF 游標和游標變量用于處理運行時動態執行的 SQL 查詢 創建游標變量需要兩個步驟: 聲明 REF 游標類型 聲明 REF 游標類型的變量 TYPE <ref_cursor_name> IS REF CURSOR [RETURN <return_type>]; 聲明強類型的 REF 游標 1、for 后是?SQL語句(而不能是 字符串) 2、cur… 必須和 return 的?類型完全一致 3、無法使用?綁定變量 TYPE my_curtype IS REF CURSORRETURN stud_det%ROWTYPE;
order_cur my_curtype;
聲明弱類型的 REF 游標,系統類型 SYS_REFCURSOR TYPE my_ctype IS REF CURSOR;
stud_cur my_ctype;
declare2 type cursor_type is ref cursor;3 stu_cursor cursor_type;4 v_stu 學生表%rowtype;5 begin6 open stu_cursor for7 select * from 學生表 where 性別='男';8 loop9 fetch stu_cursor into v_stu;10 exit when stu_cursor%notfound;11 dbms_output.put_line(v_stu.學號 ||' '||v_stu.姓名||' '||v_stu.性別||' '||v_stu.年齡);12 end loop;13 close stu_cursor;14 end; declare2 type emp_type is ref cursor;3 cur emp_type;4 name varchar2(20);5 salary number(7,2);6 begin7 open cur for 'select ename,sal from emp where job=:1'8 using 'SALESMAN';9 loop10 fetch cur into name,salary;11 exit when cur%notfound;12 dbms_output.put_line(name||':'||salary);13 end loop;14 close cur;15 end; declare2 type empcurtyp is ref cursor;3 type idlist is table of emp.empno%type;4 type namelist is table of emp.ename%type;5 type sallist is table of emp.sal%type;6 emp_cv empcurtyp;7 ids idlist;8 names namelist; sals sallist;9 row_cn number;10 begin11 open emp_cv for select empno,ename,sal from emp;12 fetch emp_cv bulk collect into ids,names,sals;13 close emp_cv;14 for i in ids.first.. ids.last loop15 dbms_output.put_line(ids(i)||' '||names(i)||' '||sals(i));16 end loop;17* end; ? |
游標變量的優點和限制 | 游標變量的功能強大,可以簡化數據處理。 游標變量的優點有: 可從不同的 SELECT 語句中提取結果集 可以作為過程的參數進行傳遞 可以引用游標的所有屬性 可以進行賦值運算 使用游標變量的限制: 不能在程序包中聲明游標變量 FOR UPDATE子句不能與游標變量一起使用 不能使用比較運算符 DECLAREv_sql VARCHAR(2000);v_b1 NUMBER(3) := 3;TYPE record_stu IS RECORD(v_id system.stu.s_id%TYPE,v_xm system.stu.s_xm%TYPE);TYPE table_stu IS TABLE OF record_stu;v_stu table_stu;cur_stu SYS_REFCURSOR;
BEGINv_sql := 'SELECT t.s_id, t.s_xm FROM stu t WHERE t.s_id <= :b1';OPEN cur_stu FOR v_sqlUSING v_b1; -- 綁定變量 : 大數據處理常用優化手段LOOPFETCH cur_stu BULK COLLECTINTO v_stu LIMIT 1; -- 數據量太少,僅當前測試使用哦,實際開發 建議 500 左右EXIT WHEN v_stu.count = 0;FOR i IN v_stu.first .. v_stu.last LOOPdbms_output.put_line('序號:' || v_stu(i).v_id || ' , ' || '姓名:' || v_stu(i).v_xm);END LOOP;END LOOP;CLOSE cur_stu;EXCEPTIONWHEN OTHERS THENdbms_output.put_line(SQLCODE || ' : ' || SQLERRM);dbms_output.put_line(dbms_utility.format_error_backtrace);
END;
? |
%type、%rowtype、record | - %type:
單條 ?記錄類型自動匹配 - %rowtype:
所有 ?記錄類型自動匹配 - record:
部分 ?記錄類型自動匹配,該變量類型允許用戶在代碼中使用“表”,以便存儲多個行數據。記錄表類型是對記錄類型的擴展,可以處理多個記錄或多行數據
|
集合操作 | 在 Oracle 中集合中,若想擴充大小有兩種方法 方式1:(手動)集合.extend(一次只申請一個空間長度) 方式2:(自動)Type <Type_name> IS TABLE OF <data_type> index by .. Oracle 下標定義和其他語言有些區別 下標從 1 開始算,而不是 0 哦。 varry 一維數組(設置長度) | type 數組名 is varray(size) of 元素類型 [not null]; size : 數組最大長度,必填項。 DECLARE ? ?TYPE varry IS VARRAY(4) OF VARCHAR2(30); -- 最大長度是 4 ? ?v_varry varry; BEGIN ? ?-- 初始化 3 個下標, 也就只能寫 3 個長度,即使定義的 有 4 個長度 ? ?v_varry ?:= varry('a', 'b', 'c'); -- 構造方法 進行初始化 ? ?FOR i IN v_varry.first .. v_varry.last LOOP ? ? ? dbms_output.put_line(v_varry (i)); ? ?END LOOP; END; / | table 多維數組 | type table_name is table of element_type[not null] [index by [binary_integer|pls_integer]]; index by : 創建一個主鍵索引,以便引用記錄表變量中的特定行. -- 下列參數下標自增(無需 顯示初始化:extend) binary_integer : ?由 Oracle來 執行,不會出現溢出,但是執行速度較慢, ? ? ? ? ? ? ? ? ? 因為它是由 Oracle 模擬執行。 pls_integer ? ?: ?由硬件即直接由 CPU 來運算,因而會出現溢出,但其執行速度 ? ? ? ? ? ? ? ? ? 較前者快許多,數據范圍:參考 ‘Oracle 官方解釋中的紅色字體’ | ?存儲單行多列 (效果同 varry 一維數組) | 這個和 VARRAY 類似。但是賦值方式稍微有點不同,不能使用同名的 構造函數 進行賦值。 有個細節:去掉 index by .. 后,是可以使用 構造函數 DECLARE ? ?-- 此例中 ?INDEX BY PLS_INTEGER 加不加都可以,具體解釋看后面 ? ?TYPE varry_stu IS TABLE OF VARCHAR2(30) INDEX BY PLS_INTEGER; ? ?v_stu_varry varry_stu; BEGIN ? ?-- varry_stu := varry_stu('a', 'b', 'c');? ? ?-- 此時 不能像 varry 使用上述 構造函數 進行初始化了哦 ? ?v_stu_varry(1) := 'a'; ? ?v_stu_varry(2) := 'b'; ? ?v_stu_varry(3) := 'c'; ? ?FOR i IN v_stu_varry.first .. v_stu_varry.last LOOP ? ? ? dbms_output.put_line(i || ' : ' || v_stu_varry(i)); ? ?END LOOP; END; / | 存儲多行多列 | TYPE <類型名> IS TABLE OF [%rowtype / record] 若想匹配所有字段,與 %rowtype 最為方便 若想匹配部分字段,與 record 最為方便 下列實例是數據倉庫中,表同步 的常見寫法 當然,實現功能的寫法有很多種,這里,只給出我認為最優的。 DECLAREi_stu_id NUMBER(3) := 3; -- 模擬入參 v_sql VARCHAR(2000);cur_stu SYS_REFCURSOR;TYPE record_stu IS RECORD(v_id stu.id%TYPE,v_name stu.name%TYPE);TYPE table_stu IS TABLE OF record_stu; -- 思考:加不加 index by ...?v_stu table_stu;BEGINv_sql := 'SELECT t.id, t.name FROM stu t WHERE t.id <= :b1';OPEN cur_stu FOR v_sqlUSING i_stu_id; -- 綁定變量 : 大數據處理常用優化手段LOOPFETCH cur_stu BULK COLLECTINTO v_stu LIMIT 2; -- 數據量太少,僅當前測試使用哦,實際開發 建議 500 左右EXIT WHEN v_stu.count = 0;-- 細節:如果此處使用 cur_stu%notfound 不足 limit n 的數據不會在操作了哦FOR i IN v_stu.first .. v_stu.last LOOPdbms_output.put_line('學號:' || v_stu(i).v_id || ' , ' || '姓名:' || v_stu(i).v_name);-- 模擬表同步(不存在時 insert、存在時 update)END LOOP;END LOOP;CLOSE cur_stu;EXCEPTIONWHEN OTHERS THENIF cur_stu%ISOPEN THENCLOSE cur_stu;END IF;dbms_output.put_line(SQLERRM);dbms_output.put_line(dbms_utility.format_error_backtrace);
END;
/
? |
何時使用 index by | PL/SQL 向?集合類型 ?中插入數據時,必須先擴展?內存空間 ,有兩種方式 ? DECLARETYPE string_array IS TABLE OF VARCHAR2(30);TYPE string_array_index IS TABLE OF VARCHAR2(30) INDEX BY PLS_INTEGER;v_a string_array;v_b string_array_index;
BEGIN-- 不加 INDEX BY... 是 可以 使用構造函數的v_a := string_array('a1', 'a2', 'a3');-- 加了 INDEX BY... 是 不能 使用構造函數的-- varry_stu := varry_stu('b1', 'b2', 'b3'); v_b(v_b.count) := 'b0'; -- 細節: 剛開始,數組為空,故 v_b.count = 0v_b(v_b.count) := 'b1'; -- 之后 count 依次遞增(切記:不可指定 count哦,不然就不遞增了,而是重復修改原記錄)v_b(v_b.count) := 'b2';-- TODO: 分別插入新數據 new1, new2-- v_av_a.extend(2);v_a(4) := 'new1';v_a(5) := 'new2';FOR i IN v_a.first .. v_a.last LOOPdbms_output.put_line(i || ' : ' || v_a(i));END LOOP;dbms_output.new_line();-- v_bv_b(v_b.count) := 'new1';v_b(v_b.count) := 'new2';FOR i IN v_b.first .. v_b.last LOOPdbms_output.put_line(i || ' : ' || v_b(i));END LOOP;
END;
/1 : a1
2 : a2
3 : a3
4 : new1
5 : new20 : b0
1 : b1
2 : b2
3 : new1
4 : new2
? | 空數組時 | - 沒加 index by 的數組必須?
初始化 - 空數組時,array.first = array.last = null;
- 空數組時,array.count = 0;
DECLARETYPE string_array IS TABLE OF VARCHAR2(30);TYPE string_array_index IS TABLE OF VARCHAR2(30) INDEX BY PLS_INTEGER;v_a string_array := string_array(); -- 必須先初始化v_b string_array_index; -- 加了 index by 相當于 默認初始化
BEGINdbms_output.put_line('v_a.first: ' || v_a.first);dbms_output.put_line('v_a.last: ' || v_a.last);dbms_output.put_line('v_a.count: ' || v_a.count);dbms_output.new_line();dbms_output.put_line('v_b.first: ' || v_b.first);dbms_output.put_line('v_b.last: ' || v_b.last);dbms_output.put_line('v_b.count: ' || v_a.count);
END;
/v_a.first:
v_a.last:
v_a.count: 0v_b.first:
v_b.last:
v_b.count: 0 ? | 清除數組元素 delete 和 置 null 的區別 | - 置 null:清除數組元素,但?
不刪除內存空間 - delete:清除數組元素,并且?
刪除內存空間
DECLARETYPE string_array_index IS TABLE OF VARCHAR2(30) INDEX BY PLS_INTEGER;v_b string_array_index;
BEGINv_b(v_b.count) := 'b1'; -- 因為 數組為空,故而 v_b.count = 0v_b(v_b.count) := 'b2';v_b(v_b.count) := 'b3';-- TODO:置 null 方式,清除數組元素dbms_output.put_line('原數組長度:' || v_b.count);v_b(0) := NULL;dbms_output.put_line('置 null 后的長度:' || v_b.count);FOR i IN v_b.first .. v_b.last LOOPdbms_output.put_line(i || ' : ' || v_b(i));END LOOP;dbms_output.new_line();-- TODO:delete 方式,清除數組元素v_b.delete(0);dbms_output.put_line('delete 后的長度:' || v_b.count);FOR i IN v_b.first .. v_b.last LOOPdbms_output.put_line(i || ' : ' || v_b(i));END LOOP;
END;
/原數組長度:3
置 null 后的長度:3
0 :
1 : b2
2 : b3delete 后的長度:2
1 : b2
2 : b3 ? | 數組遍歷時,不連續下標異常 | 數組遍歷時,是嚴格按照下標順序來的,若中間出現?斷層 (找不到下標),就會報錯 DECLARETYPE string_array_index IS TABLE OF VARCHAR2(30) INDEX BY PLS_INTEGER;v_b string_array_index;
BEGINv_b(v_b.count) := 'b1'; -- 因為 數組為空,故而 v_b.count = 0v_b(v_b.count) := 'b2';v_b(v_b.count) := 'b3';v_b.delete(1); -- 刪除 'b2'FOR i IN v_b.first .. v_b.last LOOP-- 測試時,請去掉 IF,直接 dbms_output 即可。IF v_b.exists(i) THENdbms_output.put_line(i || ' : ' || v_b(i));END IF;END LOOP;
END;
/0 : b1
2 : b3 ? |
? |
數組屬性和函數 | 屬性/函數?? ?描述 count?? ?返回集合中元素的個數 delete?? ?刪除集合中 所有 的元素及 extend delete(x)?? ?刪除元素下標為 x 的元素(對 varry 非法) delete(x, y)?? ?刪除元素下標從 x 到 y 的元素(對 varry 非法) trim?? ?從集合末端開始刪除一個元素(對 index by 非法) trim(x)?? ?從集合末端開始刪除 x 個元素 (對 index by 非法) exists(x)?? ?如果集合元素 x 已經 初始化(extend) ,則返回 true,否則返回 false extend?? ?在集合 末尾 添加一個元素(對 index by 非法) extend(x)?? ?在集合 末尾 添加 x個元素 (對 index by 非法) extend(x, n)?? ?在集合 末尾 添加元素 x 個下標為n 的 副本(對 index by 非法) first?? ?返回集合中第一個元素的下標號,對 varry 集合 始終 返回 1(除非 未初始化 則為 空) last?? ?返回集合中最后一個元素的下標號,對 varry 集合 值始終 等于 count (除非 未初始化 則為 空) limit?? ?返回 varry 集合的最大的元素個數,對 index by 無效 next(x)?? ?返回在第 x 個元素之后緊挨著它的元素下標(x+1),若 x 是最后一個元素,則返回 null prior(x)?? ?返回在第x個元素之前緊挨著它的 元素下標(x-1),如果 x 是第一個元素,則返回 null |
Cursor與 Ref Cursor區別 | 從技術底層看,兩者是相同的。普通plsql cursor在定義時是“靜態”的。而Ref cursors可以動態打開。 ? Ref cursor根據邏輯動態打開;而游標cursor定義好了就無法修改了 ref cursor可以返回給客戶端,cursor則不行。 cursor可以是全局的global ,ref cursor則必須定義在過程或函數中。 ref cursor可以在子程序間傳遞,cursor則不行。 cursor中定義的靜態sql比ref cursor效率高,所以ref cursor通常 ?①靜態游標是靜態定義,REF?游標是動態關聯; ?②使用REF?游標需REF?游標變量。 ?③REF?游標能做為參數進行傳遞,而靜態游標是不可能的。 |
總結 | 游標用于處理查詢結果集中的數據 游標類型有:隱式游標、顯式游標和 REF 游標 隱式游標由 PL/SQL 自動定義、打開和關閉 顯式游標用于處理返回多行的查詢 顯式游標可以刪除和更新活動集中的行 要處理結果集中所有記錄時,可使用循環游標 在聲明 REF 游標時,不需要將 SELECT 語句與 其關聯? |