Oracle入门(十四.10)之显式游标简介
一、上下文區域和游標
Oracle服務器分配一個稱為上下文區域的私有內存區域來存儲由SQL語句處理的數據。 每個上下文區域(因此每個SQL語句)都有一個與其關聯的游標。您可以將游標視為上下文區域的標簽,或者將其作為指向上下文區域的指針。 事實上,一個游標就是這兩個項目。二、隱式和顯式游標
有兩種類型的游標:?隱式游標:由Oracle自動為所有SQL DML語句(INSERT,UPDATE,DELETE和MERGE)以及僅返回一行的SELECT語句定義。
?顯式游標:由程序員為返回多行的查詢聲明。 您可以使用顯式游標來命名上下文區域并訪問其存儲的數據。
三、隱式游標的限制
EMPLOYEES表中有多行:
DECLAREv_salary employees.salary%TYPE; BEGINSELECT salary INTO v_salaryFROM employees;DBMS_OUTPUT.PUT_LINE(' Salary is : '||v_salary); END;ORA-01422: exact fetch returns more than requested number of rows
四、顯式游標
使用顯式游標,您可以從數據庫表中檢索多行,為檢索到的每行提供一個指針,并且一次處理一行。 以下是使用顯式游標的一些原因:?這是PL / SQL從表中檢索多行的唯一方法。
?每行由一個單獨的程序語句提取,使程序員可以更好地控制行的處理。
(1)顯式游標的例子
以下示例使用明確的游標來獲取亞洲國家的國家名稱和國定假日。
DECLARECURSOR wf_holiday_cursor IS --定義游標SELECT country_name, national_holiday_dateFROM wf_countries where region_id IN(30,34,35);v_country_name wf_countries.country_name%TYPE;v_holiday wf_countries.national_holiday_date%TYPE; BEGINOPEN wf_holiday_cursor; --打開游標LOOPFETCH wf_holiday_cursor INTO v_country_name, v_holiday; --提取游標一行EXIT WHEN wf_holiday_cursor%NOTFOUND;DBMS_OUTPUT.PUT_LINE(v_country_name||' '||v_holiday);END LOOP; CLOSE wf_holiday_cursor; --關閉游標 END;(2)顯式游標操作
由多行查詢返回的行集稱為活動集,并存儲在上下文區域中。 它的大小是符合您的搜索條件的行數。將上下文區域(由光標命名)看作一個框,并將活動集作為框的內容。 為了獲得數據,您必須打開盒子并逐個從盒子中取出每一行。 完成后,您必須關閉該框。
(3)控制顯式游標
(4)聲明和控制顯式游標
五、使用顯式游標的步驟
您首先聲明一個游標,然后使用OPEN,FETCH和CLOSE語句來控制游標。
1.在聲明部分中聲明游標。
2.打開光標。
3.從活動集中取出每行,直到該框為空。
4.關閉光標。
OPEN語句執行與游標相關的查詢,標識結果集并將光標定位在第一行之前。 FETCH語句檢索當前行并將光標前進到下一行。 當最后一行被處理完后,CLOSE語句禁用游標。
(1)聲明游標的語法
游標的活動集由游標聲明中的SELECT語句確定。句法:
CURSOR cursor_name ISselect_statement;在語法中:
cursor_name是PL / SQL標識符
select_statement是一個沒有INTO子句的SELECT語句
(2)聲明游標示例1
聲明emp_cursor游標以檢索部門中使用department_id為30的員工的employee_id和last_name列。DECLARECURSOR emp_cursor ISSELECT employee_id, last_name FROM employeesWHERE department_id =30; ...
(3)聲明游標示例2
聲明dept_cursor游標以檢索具有location_id 1700的部門的所有詳細信息。您想按department_name的升序序列提取和處理這些行。
DECLARECURSOR dept_cursor ISSELECT * FROM departmentsWHERE location_id = 1700ORDER BY department_name; ...(4)聲明游標示例3
游標聲明中的SELECT語句可以包含連接,組函數和子查詢。 此示例檢索每個至少有兩名員工的部門,并給出部門名稱和員工人數。DECLARECURSOR dept_emp_cursor ISSELECT department_name, COUNT(*) AS how_manyFROM departments d, employees eWHERE d.department_id = e.department_idGROUP BY d.department_nameHAVING COUNT(*) > 1; ...
六、聲明游標的指南
在聲明游標時:?不要在游標聲明中包含INTO子句,因為它稍后出現在FETCH語句中。
?如果需要處理特定順序的行,則在查詢中使用ORDER BY子句。
游標可以是任何有效的SELECT語句,包括連接,子查詢等等。
?如果游標聲明引用任何PL / SQL變量,則必須在聲明游標之前聲明這些變量。
(1)打開光標
OPEN語句執行與游標關聯的查詢,標識活動集并將光標指針定位到第一行。 OPEN語句包含在PL / SQL塊的可執行部分中。DECLARECURSOR emp_cursor ISSELECT employee_id, last_name FROM employeesWHERE department_id = 30; ... BEGINOPEN emp_cursor; ...OPEN語句執行以下操作:
1.為上下文區域分配內存(創建框)
2.在游標聲明中執行SELECT語句,將結果返回到活動集(用數據填充框)
3.將指針定位到活動集中的第一行
(2)從光標獲取數據
FETCH語句一次從光標中檢索一行。 每次提取后,光標前進到活動集中的下一行。 兩個變量v_empno和v_lname被聲明為保存游標中的取值。
DECLARECURSOR emp_cursor ISSELECT employee_id, last_name FROM employeesWHERE department_id =10;v_empno employees.employee_id%TYPE;v_lname employees.last_name%TYPE; BEGINOPEN emp_cursor;FETCH emp_cursor INTO v_empno, v_lname;DBMS_OUTPUT.PUT_LINE( v_empno ||' '||v_lname);... END;輸出:
200 Whalen
Statement processed.您已成功將光標中的值提取到變量中。 但是,第30部門有6名員工。只有一行被提取。 要獲取所有行,您必須使用循環。
輸出:
124 Mourgos
141 Rajs142 Davies
143 Matos
144 Vargas
Statement processed.
(3)從光標獲取數據的準則
從光標獲取數據時遵循以下準則:?在FETCH語句的INTO子句中包含與SELECT語句中的列相同數量的變量,并確保數據類型兼容。
?將每個變量與位置上的列進行匹配。?測試以查看游標是否包含行。 如果提取沒有獲取值,則在活動集中沒有剩余行要處理,并且不記錄錯誤。 最后一行被重新處理。
?您可以使用%NOTFOUND游標屬性來測試退出條件。
從光標獲取數據示例1
這個例子有什么問題?
DECLARECURSOR emp_cursor ISSELECT employee_id, last_name, salary FROM employeesWHERE department_id =30;v_empno employees.employee_id%TYPE;v_lname employees.last_name%TYPE;v_sal employees.salary%TYPE; BEGINOPEN emp_cursor;LOOPFETCH emp_cursor INTO v_empno, v_lname;EXIT WHEN emp_cursor%NOTFOUND;DBMS_OUTPUT.PUT_LINE( v_empno ||' '||v_lname);END LOOP; … END;從光標獲取數據示例2部門10中只有一名員工。執行此示例時會發生什么?
DECLARECURSOR emp_cursor ISSELECT employee_id, last_name FROM employeesWHERE department_id =10;v_empno employees.employee_id%TYPE;v_lname employees.last_name%TYPE; BEGINOPEN emp_cursor;LOOPFETCH emp_cursor INTO v_empno, v_lname;DBMS_OUTPUT.PUT_LINE( v_empno ||' '||v_lname);END LOOP; … END;(4)關閉光標
CLOSE語句禁用游標,釋放上下文區域,并取消定義活動集。 完成FETCH語句處理后關閉游標。 如果需要,您可以稍后重新打開游標。 把CLOSE想象成關閉和清空盒子,所以你不能再取出它的內容。...LOOPFETCH emp_cursor INTO v_empno, v_lname;EXIT WHEN emp_cursor%NOTFOUND;DBMS_OUTPUT.PUT_LINE( v_empno ||' '||v_lname);END LOOP; CLOSE emp_cursor; --關閉游標 END;關閉游標指南
關閉游標時請遵循以下準則:
?光標只有關閉后才能重新打開。 如果您嘗試在游標關閉后從游標讀取數據,則會引發INVALID_CURSOR異常。
?如果稍后重新打開游標,將重新執行關聯的SELECT語句,以使用來自數據庫的最新數據重新填充上下文區域。
七、把它放在一起
以下示例聲明并處理游標以獲取亞洲國家的國家名稱和國家法定節假日。DECLARECURSOR wf_holiday_cursor ISSELECT country_name, national_holiday_dateFROM wf_countries where region_id IN(30,34,35);v_country_name wf_countries.country_name%TYPE;v_holiday wf_countries.national_holiday_date%TYPE; BEGINOPEN wf_holiday_cursor;LOOPFETCH wf_holiday_cursor INTO v_country_name, v_holiday;EXIT WHEN wf_holiday_cursor%NOTFOUND;DBMS_OUTPUT.PUT_LINE(v_country_name||' '||v_holiday);END LOOP;CLOSE wf_holiday_cursor; END;
總結
以上是生活随笔為你收集整理的Oracle入门(十四.10)之显式游标简介的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 抖音收藏怎么看不到是谁收藏的
- 下一篇: Oracle入门(十四.11)之使用显式