日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Oracle 把游标说透

發布時間:2024/9/20 编程问答 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Oracle 把游标说透 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本篇主要內容如下:

4.1?游標概念

4.1.1?處理顯式游標

4.1.2?處理隱式游標

4.1.3?關于?NO_DATA_FOUND?和?%NOTFOUND的區別

4.1.4??使用游標更新和刪除數據

4.2?游標變量

4.2.1??聲明游標變量

4.2.2??游標變量操作


游標的使用

????在?PL/SQL?程序中,對于處理多行記錄的事務經常使用游標來實現。

4.1?游標概念

??在PL/SQL塊中執行SELECT、INSERT、DELETE和UPDATE語句時,ORACLE會在內存中為其分配上下文區(Context?Area),即緩沖區。游標是指向該區的一個指針,或是命名一個工作區(Work?Area),或是一種結構化數據類型。它為應用等量齊觀提供了一種對具有多行數據查詢結果集中的每一行數據分別進行單獨處理的方法,是設計嵌入式SQL語句的應用程序的常用編程方式。

?在每個用戶會話中,可以同時打開多個游標,其數量由數據庫初始化參數文件中的OPEN_CURSORS參數定義。

對于不同的SQL語句,游標的使用情況不同:

SQL語句

游標

非查詢語句

隱式的

結果是單行的查詢語句

隱式的或顯示的

結果是多行的查詢語句

顯示的

4.1.1?處理顯式游標

1.?顯式游標處理

顯式游標處理需四個?PL/SQL步驟:

l?定義/聲明游標:就是定義一個游標名,以及與其相對應的SELECT?語句。

格式:

CURSOR?cursor_name[(parameter[,?parameter]…)]?
???????????[RETURN?datatype]
????IS?
????????select_statement;

游標參數只能為輸入參數,其格式為:?

parameter_name?[IN]?datatype?[{:=?|?DEFAULT}?expression]

在指定數據類型時,不能使用長度約束。如NUMBER(4),CHAR(10)?等都是錯誤的。

[RETURN?datatype]是可選的,表示游標返回數據的數據。如果選擇,則應該嚴格與select_statement中的選擇列表在次序和數據類型上匹配。一般是記錄數據類型或帶“%ROWTYPE”的數據。

l?打開游標:就是執行游標所對應的SELECT?語句,將其查詢結果放入工作區,并且指針指向工作區的首部,標識游標結果集合。如果游標查詢語句中帶有FOR?UPDATE選項,OPEN?語句還將鎖定數據庫表中游標結果集合對應的數據行。

格式:

OPEN?cursor_name[([parameter?=>]?value[,?[parameter?=>]?value]…)];

在向游標傳遞參數時,可以使用與函數參數相同的傳值方法,即位置表示法和名稱表示法。PL/SQL?程序不能用OPEN?語句重復打開一個游標。

l?提取游標數據:就是檢索結果集合中的數據行,放入指定的輸出變量中。?

格式:

FETCH?cursor_name?INTO?{variable_list?|?record_variable?};

執行FETCH語句時,每次返回一個數據行,然后自動將游標移動指向下一個數據行。當檢索到最后一行數據時,如果再次執行FETCH語句,將操作失敗,并將游標屬性%NOTFOUND置為TRUE。所以每次執行完FETCH語句后,檢查游標屬性%NOTFOUND就可以判斷FETCH語句是否執行成功并返回一個數據行,以便確定是否給對應的變量賦了值。

l?對該記錄進行處理;

l?繼續處理,直到活動集合中沒有記錄;

l?關閉游標:當提取和處理完游標結果集合數據后,應及時關閉游標,以釋放該游標所占用的系統資源,并使該游標的工作區變成無效,不能再使用FETCH?語句取其中數據。關閉后的游標可以使用OPEN?語句重新打開。

格式:

CLOSE?cursor_name;

?????注:定義的游標不能有INTO?子句。

例1.?查詢前10名員工的信息。

DECLARE
???CURSOR?c_cursor?
???IS?SELECT?first_name?||?last_name,?Salary?
???FROM?EMPLOYEES?
???WHERE?rownum<11;???
???v_ename??EMPLOYEES.first_name%TYPE;
???v_sal????EMPLOYEES.Salary%TYPE;???
BEGIN
??OPEN?c_cursor;
??FETCH?c_cursor?INTO?v_ename,?v_sal;
??WHILE?c_cursor%FOUND?LOOP
?????DBMS_OUTPUT.PUT_LINE(v_ename||'---'||to_char(v_sal)?);
?????FETCH?c_cursor?INTO?v_ename,?v_sal;
??END?LOOP;
??CLOSE?c_cursor;
END;

例2.?游標參數的傳遞方法。

DECLARE
??DeptRec????DEPARTMENTS%ROWTYPE;
??Dept_name??DEPARTMENTS.DEPARTMENT_NAME%TYPE;
??Dept_loc???DEPARTMENTS.LOCATION_ID%TYPE;
??CURSOR?c1?IS?
??SELECT?DEPARTMENT_NAME,?LOCATION_ID?FROM?DEPARTMENTS?
??WHERE?DEPARTMENT_ID?<=?30;
??CURSOR?c2(dept_no?NUMBER?DEFAULT?10)?IS
????SELECT?DEPARTMENT_NAME,?LOCATION_ID?FROM?DEPARTMENTS?
????WHERE?DEPARTMENT_ID?<=?dept_no;
??CURSOR?c3(dept_no?NUMBER?DEFAULT?10)?IS?
????SELECT?*?FROM?DEPARTMENTS?
????WHERE?DEPARTMENTS.DEPARTMENT_ID?<=dept_no;
BEGIN
??OPEN?c1;
??LOOP
????FETCH?c1?INTO?dept_name,?dept_loc;
????EXIT?WHEN?c1%NOTFOUND;
????????DBMS_OUTPUT.PUT_LINE(dept_name||'---'||dept_loc);
????END?LOOP;
????CLOSE?c1;
????OPEN?c2;
????LOOP
????????FETCH?c2?INTO?dept_name,?dept_loc;
????????EXIT?WHEN?c2%NOTFOUND;
????????DBMS_OUTPUT.PUT_LINE(dept_name||'---'||dept_loc);
????END?LOOP;
????CLOSE?c2;
????OPEN?c3(dept_no?=>20);
????LOOP
????????FETCH?c3?INTO?deptrec;
????????EXIT?WHEN?c3%NOTFOUND;
????????DBMS_OUTPUT.PUT_LINE(deptrec.DEPARTMENT_ID||'---'||deptrec.DEPARTMENT_NAME||'---'||deptrec.LOCATION_ID);
????END?LOOP;
????CLOSE?c3;
END;

2.游標屬性

?Cursor_name%FOUND?????布爾型屬性,當最近一次提取游標操作FETCH成功則為?TRUE,否則為FALSE;

?Cursor_name%NOTFOUND???布爾型屬性,與%FOUND相反;

?Cursor_name%ISOPEN?????布爾型屬性,當游標已打開時返回?TRUE;

?Cursor_name%ROWCOUNT???數字型屬性,返回已從游標中讀取的記錄數。

例3:給工資低于1200?的員工增加工資50。

DECLARE
???v_empno??EMPLOYEES.EMPLOYEE_ID%TYPE;
???v_sal??????EMPLOYEES.Salary%TYPE;
???CURSOR?c_cursor?IS?SELECT?EMPLOYEE_ID,?Salary?FROM?EMPLOYEES;?
BEGIN
???OPEN?c_cursor;
???LOOP
??????FETCH?c_cursor?INTO?v_empno,?v_sal;
??????EXIT?WHEN?c_cursor%NOTFOUND;?
??????IF?v_sal<=1200?THEN
????????????UPDATE?EMPLOYEES?SET?Salary=Salary+50?WHERE?EMPLOYEE_ID=v_empno;
????????????DBMS_OUTPUT.PUT_LINE('編碼為'||v_empno||'工資已更新!');
??????END?IF;
???DBMS_OUTPUT.PUT_LINE('記錄數:'||?c_cursor?%ROWCOUNT);
???END?LOOP;
???CLOSE?c_cursor;
END;?

例4:沒有參數且沒有返回值的游標。

DECLARE
???v_f_name?employees.first_name%TYPE;
???v_j_id???employees.job_id%TYPE;
???CURSOR?c1???????--聲明游標,沒有參數沒有返回值
???IS
??????SELECT?first_name,?job_id?FROM?employees?
??????WHERE?department_id?=?20;
BEGIN
???OPEN?c1;????????--打開游標
???LOOP
??????FETCH?c1?INTO?v_f_name,?v_j_id;????--提取游標
??????IF?c1%FOUND?THEN
?????????DBMS_OUTPUT.PUT_LINE(v_f_name||'的崗位是'||v_j_id);
??????ELSE
?????????DBMS_OUTPUT.PUT_LINE('已經處理完結果集了');
?????????EXIT;
??????END?IF;
???END?LOOP;
???CLOSE?c1;???--關閉游標
END;

例5:有參數且沒有返回值的游標。

DECLARE
???v_f_name?employees.first_name%TYPE;
???v_h_date?employees.hire_date%TYPE;
???CURSOR?c2(dept_id?NUMBER,?j_id?VARCHAR2)?--聲明游標,有參數沒有返回值
???IS
??????SELECT?first_name,?hire_date?FROM?employees
??????WHERE?department_id?=?dept_id?AND?job_id?=?j_id;
BEGIN
???OPEN?c2(90,?'AD_VP');??--打開游標,傳遞參數值
???LOOP
??????FETCH?c2?INTO?v_f_name,?v_h_date;????--提取游標
??????IF?c2%FOUND?THEN
?????????DBMS_OUTPUT.PUT_LINE(v_f_name||'的雇傭日期是'||v_h_date);
??????ELSE
?????????DBMS_OUTPUT.PUT_LINE('已經處理完結果集了');
?????????EXIT;
??????END?IF;
???END?LOOP;
???CLOSE?c2;???--關閉游標
END;

例6:有參數且有返回值的游標。

DECLARE
???TYPE?emp_record_type?IS?RECORD(
????????f_name???employees.first_name%TYPE,
????????h_date???employees.hire_date%TYPE);
???v_emp_record?EMP_RECORD_TYPE;
???CURSOR?c3(dept_id?NUMBER,?j_id?VARCHAR2)?--聲明游標,有參數有返回值
??????????RETURN?EMP_RECORD_TYPE
???IS
??????SELECT?first_name,?hire_date?FROM?employees
??????WHERE?department_id?=?dept_id?AND?job_id?=?j_id;
BEGIN
???OPEN?c3(j_id?=>?'AD_VP',?dept_id?=>?90);??--打開游標,傳遞參數值
???LOOP
??????FETCH?c3?INTO?v_emp_record;????--提取游標
??????IF?c3%FOUND?THEN
?????????DBMS_OUTPUT.PUT_LINE(v_emp_record.f_name||'的雇傭日期是'
????????????????????????????||v_emp_record.h_date);
??????ELSE
?????????DBMS_OUTPUT.PUT_LINE('已經處理完結果集了');
?????????EXIT;
??????END?IF;
???END?LOOP;
???CLOSE?c3;???--關閉游標
END;

例7:基于游標定義記錄變量。

DECLARE
???CURSOR?c4(dept_id?NUMBER,?j_id?VARCHAR2)?--聲明游標,有參數沒有返回值
???IS
??????SELECT?first_name?f_name,?hire_date?FROM?employees
??????WHERE?department_id?=?dept_id?AND?job_id?=?j_id;
????--基于游標定義記錄變量,比聲明記錄類型變量要方便,不容易出錯
????v_emp_record?c4%ROWTYPE;
BEGIN
???OPEN?c4(90,?'AD_VP');??--打開游標,傳遞參數值
???LOOP
??????FETCH?c4?INTO?v_emp_record;????--提取游標
??????IF?c4%FOUND?THEN
?????????DBMS_OUTPUT.PUT_LINE(v_emp_record.f_name||'的雇傭日期是'
????????????????????????????||v_emp_record.hire_date);
??????ELSE
?????????DBMS_OUTPUT.PUT_LINE('已經處理完結果集了');
?????????EXIT;
??????END?IF;
???END?LOOP;
???CLOSE?c4;???--關閉游標
END;

3.?游標的FOR循環

????PL/SQL語言提供了游標FOR循環語句,自動執行游標的OPEN、FETCH、CLOSE語句和循環語句的功能;當進入循環時,游標FOR循環語句自動打開游標,并提取第一行游標數據,當程序處理完當前所提取的數據而進入下一次循環時,游標FOR循環語句自動提取下一行數據供程序處理,當提取完結果集合中的所有數據行后結束循環,并自動關閉游標。

格式:

FOR?index_variable?IN?cursor_name[(value[,?value]…)]?LOOP
????--?游標數據處理代碼
??END?LOOP;

其中:

index_variable為游標FOR?循環語句隱含聲明的索引變量,該變量為記錄變量,其結構與游標查詢語句返回的結構集合的結構相同。在程序中可以通過引用該索引記錄變量元素來讀取所提取的游標數據,index_variable中各元素的名稱與游標查詢語句選擇列表中所制定的列名相同。如果在游標查詢語句的選擇列表中存在計算列,則必須為這些計算列指定別名后才能通過游標FOR?循環語句中的索引變量來訪問這些列數據。

注:不要在程序中對游標進行人工操作;不要在程序中定義用于控制FOR循環的記錄。

例8:

DECLARE
???CURSOR?c_sal?IS?SELECT?employee_id,?first_name?||?last_name?ename,?salary
???FROM?employees?;
BEGIN
???--隱含打開游標
???FOR?v_sal?IN?c_sal?LOOP
???--隱含執行一個FETCH語句
??????DBMS_OUTPUT.PUT_LINE(to_char(v_sal.employee_id)||'---'||?v_sal.ename||'---'||to_char(v_sal.salary))?;
???--隱含監測c_sal%NOTFOUND
???END?LOOP;
--隱含關閉游標
END;

例9:當所聲明的游標帶有參數時,通過游標FOR?循環語句為游標傳遞參數。

DECLARE
??CURSOR?c_cursor(dept_no?NUMBER?DEFAULT?10)?
??IS
????SELECT?department_name,?location_id?FROM?departments?WHERE?department_id?<=?dept_no;
BEGIN
????DBMS_OUTPUT.PUT_LINE('當dept_no參數值為30:');
????FOR?c1_rec?IN?c_cursor(30)?LOOP????????DBMS_OUTPUT.PUT_LINE(c1_rec.department_name||'---'||c1_rec.location_id);
????END?LOOP;
????DBMS_OUTPUT.PUT_LINE(CHR(10)||'使用默認的dept_no參數值10:');
????FOR?c1_rec?IN?c_cursor?LOOP????????DBMS_OUTPUT.PUT_LINE(c1_rec.department_name||'---'||c1_rec.location_id);
????END?LOOP;
END;

例10:PL/SQL還允許在游標FOR循環語句中使用子查詢來實現游標的功能。

BEGIN
????FOR?c1_rec?IN(SELECT?department_name,?location_id?FROM?departments)?LOOP????????DBMS_OUTPUT.PUT_LINE(c1_rec.department_name||'---'||c1_rec.location_id);
????END?LOOP;
END;

4.1.2?處理隱式游標

顯式游標主要是用于對查詢語句的處理,尤其是在查詢結果為多條記錄的情況下;而對于非查詢語句,如修改、刪除操作,則由ORACLE?系統自動地為這些操作設置游標并創建其工作區,這些由系統隱含創建的游標稱為隱式游標,隱式游標的名字為SQL,這是由ORACLE?系統定義的。對于隱式游標的操作,如定義、打開、取值及關閉操作,都由ORACLE?系統自動地完成,無需用戶進行處理。用戶只能通過隱式游標的相關屬性,來完成相應的操作。在隱式游標的工作區中,所存放的數據是與用戶自定義的顯示游標無關的、最新處理的一條SQL?語句所包含的數據。

格式調用為:?SQL%

注:INSERT,?UPDATE,?DELETE,?SELECT?語句中不必明確定義游標。

隱式游標屬性

屬性

SELECT

INSERT

UPDATE

DELETE

SQL%ISOPEN

FALSE

FALSE

FALSE

FALSE

SQL%FOUND

TRUE

有結果

成功

成功

SQL%FOUND

FALSE

沒結果

失敗

失敗

SQL%NOTFUOND

TRUE

沒結果

失敗

失敗

SQL%NOTFOUND

FALSE

有結果

成功

失敗

SQL%ROWCOUNT

返回行數,只為1

插入的行數

修改的行數

刪除的行數

例11:?刪除EMPLOYEES表中某部門的所有員工,如果該部門中已沒有員工,則在DEPARTMENT表中刪除該部門。

DECLARE
????V_deptno?department_id%TYPE?:=&p_deptno;
BEGIN
????DELETE?FROM?employees?WHERE?department_id=v_deptno;
????IF?SQL%NOTFOUND?THEN
????????DELETE?FROM?departments?WHERE?department_id=v_deptno;
????END?IF;
END;

例12:?通過隱式游標SQL的%ROWCOUNT屬性來了解修改了多少行。

DECLARE
???v_rows?NUMBER;
BEGIN
--更新數據
???UPDATE?employees?SET?salary?=?30000
???WHERE?department_id?=?90?AND?job_id?=?'AD_VP';
--獲取默認游標的屬性值
???v_rows?:=?SQL%ROWCOUNT;
???DBMS_OUTPUT.PUT_LINE('更新了'||v_rows||'個雇員的工資');
--回退更新,以便使數據庫的數據保持原樣
???ROLLBACK;
END;

?

4.1.3?關于?NO_DATA_FOUND?和?%NOTFOUND的區別

SELECT?…?INTO?語句觸發?NO_DATA_FOUND;

當一個顯式游標的WHERE子句未找到時觸發%NOTFOUND;

當UPDATE或DELETE?語句的WHERE?子句未找到時觸發?SQL%NOTFOUND;在提取循環中要用?%NOTFOUND?或%FOUND?來確定循環的退出條件,不要用?NO_DATA_FOUND.4.1.4??使用游標更新和刪除數據

游標修改和刪除操作是指在游標定位下,修改或刪除表中指定的數據行。這時,要求游標查詢語句中必須使用FOR?UPDATE選項,以便在打開游標時鎖定游標結果集合在表中對應數據行的所有列和部分列。

為了對正在處理(查詢)的行不被另外的用戶改動,ORACLE?提供一個?FOR?UPDATE?子句來對所選擇的行進行鎖住。該需求迫使ORACLE鎖定游標結果集合的行,可以防止其他事務處理更新或刪除相同的行,直到您的事務處理提交或回退為止。

語法:

SELECT?column_list?FROM?table_list?FOR?UPDATE?[OF?column[,?column]…]?[NOWAIT]

????如果另一個會話已對活動集中的行加了鎖,那么SELECT?FOR?UPDATE操作一直等待到其它的會話釋放這些鎖后才繼續自己的操作,對于這種情況,當加上NOWAIT子句時,如果這些行真的被另一個會話鎖定,則OPEN立即返回并給出:

ORA-0054?:resource?busy??and??acquire?with?nowait?specified.

如果使用?FOR?UPDATE?聲明游標,則可在DELETE和UPDATE?語句中使用

WHERE?CURRENT?OF?cursor_name子句,修改或刪除游標結果集合當前行對應的數據庫表中的數據行。

例13:從EMPLOYEES表中查詢某部門的員工情況,將其工資最低定為?1500;

DECLARE?
????V_deptno?employees.department_id%TYPE?:=&p_deptno;
????CURSOR?emp_cursor?
??IS?
??SELECT?employees.employee_id,?employees.salary?
????FROM?employees?WHERE?employees.department_id=v_deptno
??FOR?UPDATE?NOWAIT;
BEGIN
????FOR?emp_record?IN?emp_cursor?LOOP
????IF?emp_record.salary?<?1500?THEN
????????UPDATE?employees?SET?salary=1500
????WHERE?CURRENT?OF?emp_cursor;
????END?IF;
????END?LOOP;
--????COMMIT;
END;?

例14:將EMPLOYEES表中部門編碼為90、崗位為AD_VP的雇員的工資都更新為2000元;

DECLARE
???v_emp_record?employees%ROWTYPE;
???CURSOR?c1
???IS
??????SELECT?*?FROM?employees?FOR?UPDATE;
BEGIN
???OPEN?c1;
???LOOP
??????FETCH?c1?INTO?v_emp_record;
??????EXIT?WHEN?c1%NOTFOUND;
??????IF?v_emp_record.department_id?=?90?AND
?????????v_emp_record.job_id?=?'AD_VP'
??????THEN
?????????UPDATE?employees?SET?salary?=?20000
?????????WHERE?CURRENT?OF?c1;??--更新當前游標行對應的數據行
??????END?IF;
???END?LOOP;
???COMMIT;???--提交已經修改的數據
???CLOSE?c1;
END;

4.2?游標變量

與游標一樣,游標變量也是一個指向多行查詢結果集合中當前數據行的指針。但與游標不同的是,游標變量是動態的,而游標是靜態的。游標只能與指定的查詢相連,即固定指向一個查詢的內存處理區域,而游標變量則可與不同的查詢語句相連,它可以指向不同查詢語句的內存處理區域(但不能同時指向多個內存處理區域,在某一時刻只能與一個查詢語句相連),只要這些查詢語句的返回類型兼容即可。

4.2.1??聲明游標變量

游標變量為一個指針,它屬于參照類型,所以在聲明游標變量類型之前必須先定義游標變量類型。在PL/SQL中,可以在塊、子程序和包的聲明區域內定義游標變量類型。

語法格式為:

TYPE?ref_type_name?IS?REF?CURSOR
?[?RETURN?return_type];

其中:ref_type_name為新定義的游標變量類型名稱;

??return_type?為游標變量的返回值類型,它必須為記錄變量。

在定義游標變量類型時,可以采用強類型定義和弱類型定義兩種。強類型定義必須指定游標變量的返回值類型,而弱類型定義則不說明返回值類型。

聲明一個游標變量的兩個步驟:

步驟一:定義一個REF?CURSOU數據類型,如:

TYPE?ref_cursor_type?IS?REF?CURSOR;

步驟二:聲明一個該數據類型的游標變量,如:

cv_ref?REF_CURSOR_TYPE;

例:創建兩個強類型定義游標變量和一個弱類型游標變量:

DECLARE
????TYPE?deptrecord?IS?RECORD(
????????Deptno?departments.department_id%TYPE,
????????Dname?departments.department_name%TYPE,
????????Loc?departments.location_id%TYPE
????);
????TYPE?deptcurtype?IS?REF?CURSOR?RETURN?departments%ROWTYPE;
????TYPE?deptcurtyp1?IS?REF?CURSOR?RETURN?deptrecord;
????TYPE?curtype?IS?REF?CURSOR;
????Dept_c1?deptcurtype;
????Dept_c2?deptcurtyp1;
????Cv?curtype;

4.2.2??游標變量操作

與游標一樣,游標變量操作也包括打開、提取和關閉三個步驟。

1.?打開游標變量

打開游標變量時使用的是OPEN…FOR?語句。格式為:

OPEN?{cursor_variable_name?|?:host_cursor_variable_name}
FOR?select_statement;

其中:cursor_variable_name為游標變量,host_cursor_variable_name為PL/SQL主機環境(如OCI:?ORACLE?Call?Interface,Pro*c?程序等)中聲明的游標變量。

OPEN…FOR?語句可以在關閉當前的游標變量之前重新打開游標變量,而不會導致CURSOR_ALREAD_OPEN異常錯誤。新打開游標變量時,前一個查詢的內存處理區將被釋放。

2.?提取游標變量數據

使用FETCH語句提取游標變量結果集合中的數據。格式為:

FETCH?{cursor_variable_name?|?:host_cursor_variable_name}
INTO?{variable?[,?variable]…|?record_variable};

其中:cursor_variable_name和host_cursor_variable_name分別為游標變量和宿主游標變量名稱;variable和record_variable分別為普通變量和記錄變量名稱。

3.?關閉游標變量

CLOSE語句關閉游標變量,格式為:

CLOSE?{cursor_variable_name?|?:host_cursor_variable_name}

其中:cursor_variable_name和host_cursor_variable_name分別為游標變量和宿主游標變量名稱,如果應用程序試圖關閉一個未打開的游標變量,則將導致INVALID_CURSOR異常錯誤。

例15:強類型參照游標變量類型

DECLARE
????TYPE?emp_job_rec?IS?RECORD(
????????Employee_id?employees.employee_id%TYPE,
????????Employee_name?employees.first_name%TYPE,
????????Job_title?employees.job_id%TYPE
????);
????TYPE?emp_job_refcur_type?IS?REF?CURSOR?RETURN?emp_job_rec;
????Emp_refcur?emp_job_refcur_type?;
????Emp_job?emp_job_rec;
BEGIN
????OPEN?emp_refcur?FOR?
????SELECT?employees.employee_id,?employees.first_name||employees.last_name,?employees.job_id?
??FROM?employees?
??ORDER?BY?employees.department_id;
????FETCH?emp_refcur?INTO?emp_job;
????WHILE?emp_refcur%FOUND?LOOP
???????DBMS_OUTPUT.PUT_LINE(emp_job.employee_id||':?'||emp_job.employee_name||'?is?a?'||emp_job.job_title);
????FETCH?emp_refcur?INTO?emp_job;
????END?LOOP;
END;

例16:弱類型參照游標變量類型

PROMPT
PROMPT?'What?table?would?you?like?to?see?'
ACCEPT?tab?PROMPT?'(D)epartment,?or?(E)mployees:'
DECLARE
????Type?refcur_t?IS?REF?CURSOR;
????Refcur?refcur_t;
????TYPE?sample_rec_type?IS?RECORD?(
????????Id?number,
????????Description?VARCHAR2?(30)
????);
????sample?sample_rec_type;
????selection?varchar2(1)?:=?UPPER?(SUBSTR?('&tab',?1,?1));
BEGIN
????IF?selection='D'?THEN
????????OPEN?refcur?FOR?
????SELECT?departments.department_id,?departments.department_name?FROM?departments;
????????DBMS_OUTPUT.PUT_LINE('Department?data');
????ELSIF?selection='E'?THEN
????????OPEN?refcur?FOR?
????SELECT?employees.employee_id,?employees.first_name||'?is?a?'||employees.job_id?FROM?employees;
????????DBMS_OUTPUT.PUT_LINE('Employee?data');
????ELSE
????????DBMS_OUTPUT.PUT_LINE('Please?enter?''D''?or?''E''');
????????RETURN;
????END?IF;
????DBMS_OUTPUT.PUT_LINE('----------------------');
????FETCH?refcur?INTO?sample;
????WHILE?refcur%FOUND?LOOP
????????DBMS_OUTPUT.PUT_LINE(sample.id||':?'||sample.description);
????????FETCH?refcur?INTO?sample;
????END?LOOP;
????CLOSE?refcur;
END;

例17:使用游標變量(沒有RETURN子句)

DECLARE
--定義一個游標數據類型
???TYPE?emp_cursor_type?IS?REF?CURSOR;
--聲明一個游標變量
???c1?EMP_CURSOR_TYPE;
--聲明兩個記錄變量
???v_emp_record?employees%ROWTYPE;
???v_reg_record?regions%ROWTYPE;
BEGIN
???OPEN?c1?FOR?SELECT?*?FROM?employees?WHERE?department_id?=?20;
???LOOP
??????FETCH?c1?INTO?v_emp_record;
??????EXIT?WHEN?c1%NOTFOUND;
??????DBMS_OUTPUT.PUT_LINE(v_emp_record.first_name||'的雇傭日期是'
????????????????????????????||v_emp_record.hire_date);
???END?LOOP;
--將同一個游標變量對應到另一個SELECT語句
???OPEN?c1?FOR?SELECT?*?FROM?regions?WHERE?region_id?IN(1,2);
???LOOP
??????FETCH?c1?INTO?v_reg_record;
??????EXIT?WHEN?c1%NOTFOUND;
??????DBMS_OUTPUT.PUT_LINE(v_reg_record.region_id||'表示'
????????????????????????????||v_reg_record.region_name);
???END?LOOP;
???CLOSE?c1;
END;

例18:使用游標變量(有RETURN子句)

DECLARE
--定義一個與employees表中的這幾個列相同的記錄數據類型
???TYPE?emp_record_type?IS?RECORD(
????????f_name???employees.first_name%TYPE,
????????h_date???employees.hire_date%TYPE,
????????j_id?????employees.job_id%TYPE);
--聲明一個該記錄數據類型的記錄變量
???v_emp_record?EMP_RECORD_TYPE;
--定義一個游標數據類型
???TYPE?emp_cursor_type?IS?REF?CURSOR
????????RETURN?EMP_RECORD_TYPE;
--聲明一個游標變量
???c1?EMP_CURSOR_TYPE;
BEGIN
???OPEN?c1?FOR?SELECT?first_name,?hire_date,?job_id
???????????????FROM?employees?WHERE?department_id?=?20;
???LOOP
??????FETCH?c1?INTO?v_emp_record;
??????EXIT?WHEN?c1%NOTFOUND;
??????DBMS_OUTPUT.PUT_LINE('雇員名稱:'||v_emp_record.f_name
????????????????||'??雇傭日期:'||v_emp_record.h_date
????????????????||'??崗位:'||v_emp_record.j_id);
???END?LOOP;
???CLOSE?c1;
END;

本篇主要內容如下:

4.1?游標概念

4.1.1?處理顯式游標

4.1.2?處理隱式游標

4.1.3?關于?NO_DATA_FOUND?和?%NOTFOUND的區別

4.1.4??使用游標更新和刪除數據

4.2?游標變量

4.2.1??聲明游標變量

4.2.2??游標變量操作


游標的使用

????在?PL/SQL?程序中,對于處理多行記錄的事務經常使用游標來實現。

4.1?游標概念

??在PL/SQL塊中執行SELECT、INSERT、DELETE和UPDATE語句時,ORACLE會在內存中為其分配上下文區(Context?Area),即緩沖區。游標是指向該區的一個指針,或是命名一個工作區(Work?Area),或是一種結構化數據類型。它為應用等量齊觀提供了一種對具有多行數據查詢結果集中的每一行數據分別進行單獨處理的方法,是設計嵌入式SQL語句的應用程序的常用編程方式。

?在每個用戶會話中,可以同時打開多個游標,其數量由數據庫初始化參數文件中的OPEN_CURSORS參數定義。

對于不同的SQL語句,游標的使用情況不同:

SQL語句

游標

非查詢語句

隱式的

結果是單行的查詢語句

隱式的或顯示的

結果是多行的查詢語句

顯示的

4.1.1?處理顯式游標

1.?顯式游標處理

顯式游標處理需四個?PL/SQL步驟:

l?定義/聲明游標:就是定義一個游標名,以及與其相對應的SELECT?語句。

格式:

CURSOR?cursor_name[(parameter[,?parameter]…)]?
???????????[RETURN?datatype]
????IS?
????????select_statement;

游標參數只能為輸入參數,其格式為:?

parameter_name?[IN]?datatype?[{:=?|?DEFAULT}?expression]

在指定數據類型時,不能使用長度約束。如NUMBER(4),CHAR(10)?等都是錯誤的。

[RETURN?datatype]是可選的,表示游標返回數據的數據。如果選擇,則應該嚴格與select_statement中的選擇列表在次序和數據類型上匹配。一般是記錄數據類型或帶“%ROWTYPE”的數據。

l?打開游標:就是執行游標所對應的SELECT?語句,將其查詢結果放入工作區,并且指針指向工作區的首部,標識游標結果集合。如果游標查詢語句中帶有FOR?UPDATE選項,OPEN?語句還將鎖定數據庫表中游標結果集合對應的數據行。

格式:

OPEN?cursor_name[([parameter?=>]?value[,?[parameter?=>]?value]…)];

在向游標傳遞參數時,可以使用與函數參數相同的傳值方法,即位置表示法和名稱表示法。PL/SQL?程序不能用OPEN?語句重復打開一個游標。

l?提取游標數據:就是檢索結果集合中的數據行,放入指定的輸出變量中。?

格式:

FETCH?cursor_name?INTO?{variable_list?|?record_variable?};

執行FETCH語句時,每次返回一個數據行,然后自動將游標移動指向下一個數據行。當檢索到最后一行數據時,如果再次執行FETCH語句,將操作失敗,并將游標屬性%NOTFOUND置為TRUE。所以每次執行完FETCH語句后,檢查游標屬性%NOTFOUND就可以判斷FETCH語句是否執行成功并返回一個數據行,以便確定是否給對應的變量賦了值。

l?對該記錄進行處理;

l?繼續處理,直到活動集合中沒有記錄;

l?關閉游標:當提取和處理完游標結果集合數據后,應及時關閉游標,以釋放該游標所占用的系統資源,并使該游標的工作區變成無效,不能再使用FETCH?語句取其中數據。關閉后的游標可以使用OPEN?語句重新打開。

格式:

CLOSE?cursor_name;

?????注:定義的游標不能有INTO?子句。

例1.?查詢前10名員工的信息。

DECLARE
???CURSOR?c_cursor?
???IS?SELECT?first_name?||?last_name,?Salary?
???FROM?EMPLOYEES?
???WHERE?rownum<11;???
???v_ename??EMPLOYEES.first_name%TYPE;
???v_sal????EMPLOYEES.Salary%TYPE;???
BEGIN
??OPEN?c_cursor;
??FETCH?c_cursor?INTO?v_ename,?v_sal;
??WHILE?c_cursor%FOUND?LOOP
?????DBMS_OUTPUT.PUT_LINE(v_ename||'---'||to_char(v_sal)?);
?????FETCH?c_cursor?INTO?v_ename,?v_sal;
??END?LOOP;
??CLOSE?c_cursor;
END;

例2.?游標參數的傳遞方法。

DECLARE
??DeptRec????DEPARTMENTS%ROWTYPE;
??Dept_name??DEPARTMENTS.DEPARTMENT_NAME%TYPE;
??Dept_loc???DEPARTMENTS.LOCATION_ID%TYPE;
??CURSOR?c1?IS?
??SELECT?DEPARTMENT_NAME,?LOCATION_ID?FROM?DEPARTMENTS?
??WHERE?DEPARTMENT_ID?<=?30;
??CURSOR?c2(dept_no?NUMBER?DEFAULT?10)?IS
????SELECT?DEPARTMENT_NAME,?LOCATION_ID?FROM?DEPARTMENTS?
????WHERE?DEPARTMENT_ID?<=?dept_no;
??CURSOR?c3(dept_no?NUMBER?DEFAULT?10)?IS?
????SELECT?*?FROM?DEPARTMENTS?
????WHERE?DEPARTMENTS.DEPARTMENT_ID?<=dept_no;
BEGIN
??OPEN?c1;
??LOOP
????FETCH?c1?INTO?dept_name,?dept_loc;
????EXIT?WHEN?c1%NOTFOUND;
????????DBMS_OUTPUT.PUT_LINE(dept_name||'---'||dept_loc);
????END?LOOP;
????CLOSE?c1;
????OPEN?c2;
????LOOP
????????FETCH?c2?INTO?dept_name,?dept_loc;
????????EXIT?WHEN?c2%NOTFOUND;
????????DBMS_OUTPUT.PUT_LINE(dept_name||'---'||dept_loc);
????END?LOOP;
????CLOSE?c2;
????OPEN?c3(dept_no?=>20);
????LOOP
????????FETCH?c3?INTO?deptrec;
????????EXIT?WHEN?c3%NOTFOUND;
????????DBMS_OUTPUT.PUT_LINE(deptrec.DEPARTMENT_ID||'---'||deptrec.DEPARTMENT_NAME||'---'||deptrec.LOCATION_ID);
????END?LOOP;
????CLOSE?c3;
END;

2.游標屬性

?Cursor_name%FOUND?????布爾型屬性,當最近一次提取游標操作FETCH成功則為?TRUE,否則為FALSE;

?Cursor_name%NOTFOUND???布爾型屬性,與%FOUND相反;

?Cursor_name%ISOPEN?????布爾型屬性,當游標已打開時返回?TRUE;

?Cursor_name%ROWCOUNT???數字型屬性,返回已從游標中讀取的記錄數。

例3:給工資低于1200?的員工增加工資50。

DECLARE
???v_empno??EMPLOYEES.EMPLOYEE_ID%TYPE;
???v_sal??????EMPLOYEES.Salary%TYPE;
???CURSOR?c_cursor?IS?SELECT?EMPLOYEE_ID,?Salary?FROM?EMPLOYEES;?
BEGIN
???OPEN?c_cursor;
???LOOP
??????FETCH?c_cursor?INTO?v_empno,?v_sal;
??????EXIT?WHEN?c_cursor%NOTFOUND;?
??????IF?v_sal<=1200?THEN
????????????UPDATE?EMPLOYEES?SET?Salary=Salary+50?WHERE?EMPLOYEE_ID=v_empno;
????????????DBMS_OUTPUT.PUT_LINE('編碼為'||v_empno||'工資已更新!');
??????END?IF;
???DBMS_OUTPUT.PUT_LINE('記錄數:'||?c_cursor?%ROWCOUNT);
???END?LOOP;
???CLOSE?c_cursor;
END;?

例4:沒有參數且沒有返回值的游標。

DECLARE
???v_f_name?employees.first_name%TYPE;
???v_j_id???employees.job_id%TYPE;
???CURSOR?c1???????--聲明游標,沒有參數沒有返回值
???IS
??????SELECT?first_name,?job_id?FROM?employees?
??????WHERE?department_id?=?20;
BEGIN
???OPEN?c1;????????--打開游標
???LOOP
??????FETCH?c1?INTO?v_f_name,?v_j_id;????--提取游標
??????IF?c1%FOUND?THEN
?????????DBMS_OUTPUT.PUT_LINE(v_f_name||'的崗位是'||v_j_id);
??????ELSE
?????????DBMS_OUTPUT.PUT_LINE('已經處理完結果集了');
?????????EXIT;
??????END?IF;
???END?LOOP;
???CLOSE?c1;???--關閉游標
END;

例5:有參數且沒有返回值的游標。

DECLARE
???v_f_name?employees.first_name%TYPE;
???v_h_date?employees.hire_date%TYPE;
???CURSOR?c2(dept_id?NUMBER,?j_id?VARCHAR2)?--聲明游標,有參數沒有返回值
???IS
??????SELECT?first_name,?hire_date?FROM?employees
??????WHERE?department_id?=?dept_id?AND?job_id?=?j_id;
BEGIN
???OPEN?c2(90,?'AD_VP');??--打開游標,傳遞參數值
???LOOP
??????FETCH?c2?INTO?v_f_name,?v_h_date;????--提取游標
??????IF?c2%FOUND?THEN
?????????DBMS_OUTPUT.PUT_LINE(v_f_name||'的雇傭日期是'||v_h_date);
??????ELSE
?????????DBMS_OUTPUT.PUT_LINE('已經處理完結果集了');
?????????EXIT;
??????END?IF;
???END?LOOP;
???CLOSE?c2;???--關閉游標
END;

例6:有參數且有返回值的游標。

DECLARE
???TYPE?emp_record_type?IS?RECORD(
????????f_name???employees.first_name%TYPE,
????????h_date???employees.hire_date%TYPE);
???v_emp_record?EMP_RECORD_TYPE;
???CURSOR?c3(dept_id?NUMBER,?j_id?VARCHAR2)?--聲明游標,有參數有返回值
??????????RETURN?EMP_RECORD_TYPE
???IS
??????SELECT?first_name,?hire_date?FROM?employees
??????WHERE?department_id?=?dept_id?AND?job_id?=?j_id;
BEGIN
???OPEN?c3(j_id?=>?'AD_VP',?dept_id?=>?90);??--打開游標,傳遞參數值
???LOOP
??????FETCH?c3?INTO?v_emp_record;????--提取游標
??????IF?c3%FOUND?THEN
?????????DBMS_OUTPUT.PUT_LINE(v_emp_record.f_name||'的雇傭日期是'
????????????????????????????||v_emp_record.h_date);
??????ELSE
?????????DBMS_OUTPUT.PUT_LINE('已經處理完結果集了');
?????????EXIT;
??????END?IF;
???END?LOOP;
???CLOSE?c3;???--關閉游標
END;

例7:基于游標定義記錄變量。

DECLARE
???CURSOR?c4(dept_id?NUMBER,?j_id?VARCHAR2)?--聲明游標,有參數沒有返回值
???IS
??????SELECT?first_name?f_name,?hire_date?FROM?employees
??????WHERE?department_id?=?dept_id?AND?job_id?=?j_id;
????--基于游標定義記錄變量,比聲明記錄類型變量要方便,不容易出錯
????v_emp_record?c4%ROWTYPE;
BEGIN
???OPEN?c4(90,?'AD_VP');??--打開游標,傳遞參數值
???LOOP
??????FETCH?c4?INTO?v_emp_record;????--提取游標
??????IF?c4%FOUND?THEN
?????????DBMS_OUTPUT.PUT_LINE(v_emp_record.f_name||'的雇傭日期是'
????????????????????????????||v_emp_record.hire_date);
??????ELSE
?????????DBMS_OUTPUT.PUT_LINE('已經處理完結果集了');
?????????EXIT;
??????END?IF;
???END?LOOP;
???CLOSE?c4;???--關閉游標
END;

3.?游標的FOR循環

????PL/SQL語言提供了游標FOR循環語句,自動執行游標的OPEN、FETCH、CLOSE語句和循環語句的功能;當進入循環時,游標FOR循環語句自動打開游標,并提取第一行游標數據,當程序處理完當前所提取的數據而進入下一次循環時,游標FOR循環語句自動提取下一行數據供程序處理,當提取完結果集合中的所有數據行后結束循環,并自動關閉游標。

格式:

FOR?index_variable?IN?cursor_name[(value[,?value]…)]?LOOP
????--?游標數據處理代碼
??END?LOOP;

其中:

index_variable為游標FOR?循環語句隱含聲明的索引變量,該變量為記錄變量,其結構與游標查詢語句返回的結構集合的結構相同。在程序中可以通過引用該索引記錄變量元素來讀取所提取的游標數據,index_variable中各元素的名稱與游標查詢語句選擇列表中所制定的列名相同。如果在游標查詢語句的選擇列表中存在計算列,則必須為這些計算列指定別名后才能通過游標FOR?循環語句中的索引變量來訪問這些列數據。

注:不要在程序中對游標進行人工操作;不要在程序中定義用于控制FOR循環的記錄。

例8:

DECLARE
???CURSOR?c_sal?IS?SELECT?employee_id,?first_name?||?last_name?ename,?salary
???FROM?employees?;
BEGIN
???--隱含打開游標
???FOR?v_sal?IN?c_sal?LOOP
???--隱含執行一個FETCH語句
??????DBMS_OUTPUT.PUT_LINE(to_char(v_sal.employee_id)||'---'||?v_sal.ename||'---'||to_char(v_sal.salary))?;
???--隱含監測c_sal%NOTFOUND
???END?LOOP;
--隱含關閉游標
END;

例9:當所聲明的游標帶有參數時,通過游標FOR?循環語句為游標傳遞參數。

DECLARE
??CURSOR?c_cursor(dept_no?NUMBER?DEFAULT?10)?
??IS
????SELECT?department_name,?location_id?FROM?departments?WHERE?department_id?<=?dept_no;
BEGIN
????DBMS_OUTPUT.PUT_LINE('當dept_no參數值為30:');
????FOR?c1_rec?IN?c_cursor(30)?LOOP????????DBMS_OUTPUT.PUT_LINE(c1_rec.department_name||'---'||c1_rec.location_id);
????END?LOOP;
????DBMS_OUTPUT.PUT_LINE(CHR(10)||'使用默認的dept_no參數值10:');
????FOR?c1_rec?IN?c_cursor?LOOP????????DBMS_OUTPUT.PUT_LINE(c1_rec.department_name||'---'||c1_rec.location_id);
????END?LOOP;
END;

例10:PL/SQL還允許在游標FOR循環語句中使用子查詢來實現游標的功能。

BEGIN
????FOR?c1_rec?IN(SELECT?department_name,?location_id?FROM?departments)?LOOP????????DBMS_OUTPUT.PUT_LINE(c1_rec.department_name||'---'||c1_rec.location_id);
????END?LOOP;
END;

4.1.2?處理隱式游標

顯式游標主要是用于對查詢語句的處理,尤其是在查詢結果為多條記錄的情況下;而對于非查詢語句,如修改、刪除操作,則由ORACLE?系統自動地為這些操作設置游標并創建其工作區,這些由系統隱含創建的游標稱為隱式游標,隱式游標的名字為SQL,這是由ORACLE?系統定義的。對于隱式游標的操作,如定義、打開、取值及關閉操作,都由ORACLE?系統自動地完成,無需用戶進行處理。用戶只能通過隱式游標的相關屬性,來完成相應的操作。在隱式游標的工作區中,所存放的數據是與用戶自定義的顯示游標無關的、最新處理的一條SQL?語句所包含的數據。

格式調用為:?SQL%

注:INSERT,?UPDATE,?DELETE,?SELECT?語句中不必明確定義游標。

隱式游標屬性

屬性

SELECT

INSERT

UPDATE

DELETE

SQL%ISOPEN

FALSE

FALSE

FALSE

FALSE

SQL%FOUND

TRUE

有結果

成功

成功

SQL%FOUND

FALSE

沒結果

失敗

失敗

SQL%NOTFUOND

TRUE

沒結果

失敗

失敗

SQL%NOTFOUND

FALSE

有結果

成功

失敗

SQL%ROWCOUNT

返回行數,只為1

插入的行數

修改的行數

刪除的行數

例11:?刪除EMPLOYEES表中某部門的所有員工,如果該部門中已沒有員工,則在DEPARTMENT表中刪除該部門。

DECLARE
????V_deptno?department_id%TYPE?:=&p_deptno;
BEGIN
????DELETE?FROM?employees?WHERE?department_id=v_deptno;
????IF?SQL%NOTFOUND?THEN
????????DELETE?FROM?departments?WHERE?department_id=v_deptno;
????END?IF;
END;

例12:?通過隱式游標SQL的%ROWCOUNT屬性來了解修改了多少行。

DECLARE
???v_rows?NUMBER;
BEGIN
--更新數據
???UPDATE?employees?SET?salary?=?30000
???WHERE?department_id?=?90?AND?job_id?=?'AD_VP';
--獲取默認游標的屬性值
???v_rows?:=?SQL%ROWCOUNT;
???DBMS_OUTPUT.PUT_LINE('更新了'||v_rows||'個雇員的工資');
--回退更新,以便使數據庫的數據保持原樣
???ROLLBACK;
END;

?

4.1.3?關于?NO_DATA_FOUND?和?%NOTFOUND的區別

SELECT?…?INTO?語句觸發?NO_DATA_FOUND;

當一個顯式游標的WHERE子句未找到時觸發%NOTFOUND;

當UPDATE或DELETE?語句的WHERE?子句未找到時觸發?SQL%NOTFOUND;在提取循環中要用?%NOTFOUND?或%FOUND?來確定循環的退出條件,不要用?NO_DATA_FOUND.4.1.4??使用游標更新和刪除數據

游標修改和刪除操作是指在游標定位下,修改或刪除表中指定的數據行。這時,要求游標查詢語句中必須使用FOR?UPDATE選項,以便在打開游標時鎖定游標結果集合在表中對應數據行的所有列和部分列。

為了對正在處理(查詢)的行不被另外的用戶改動,ORACLE?提供一個?FOR?UPDATE?子句來對所選擇的行進行鎖住。該需求迫使ORACLE鎖定游標結果集合的行,可以防止其他事務處理更新或刪除相同的行,直到您的事務處理提交或回退為止。

語法:

SELECT?column_list?FROM?table_list?FOR?UPDATE?[OF?column[,?column]…]?[NOWAIT]

????如果另一個會話已對活動集中的行加了鎖,那么SELECT?FOR?UPDATE操作一直等待到其它的會話釋放這些鎖后才繼續自己的操作,對于這種情況,當加上NOWAIT子句時,如果這些行真的被另一個會話鎖定,則OPEN立即返回并給出:

ORA-0054?:resource?busy??and??acquire?with?nowait?specified.

如果使用?FOR?UPDATE?聲明游標,則可在DELETE和UPDATE?語句中使用

WHERE?CURRENT?OF?cursor_name子句,修改或刪除游標結果集合當前行對應的數據庫表中的數據行。

例13:從EMPLOYEES表中查詢某部門的員工情況,將其工資最低定為?1500;

DECLARE?
????V_deptno?employees.department_id%TYPE?:=&p_deptno;
????CURSOR?emp_cursor?
??IS?
??SELECT?employees.employee_id,?employees.salary?
????FROM?employees?WHERE?employees.department_id=v_deptno
??FOR?UPDATE?NOWAIT;
BEGIN
????FOR?emp_record?IN?emp_cursor?LOOP
????IF?emp_record.salary?<?1500?THEN
????????UPDATE?employees?SET?salary=1500
????WHERE?CURRENT?OF?emp_cursor;
????END?IF;
????END?LOOP;
--????COMMIT;
END;?

例14:將EMPLOYEES表中部門編碼為90、崗位為AD_VP的雇員的工資都更新為2000元;

DECLARE
???v_emp_record?employees%ROWTYPE;
???CURSOR?c1
???IS
??????SELECT?*?FROM?employees?FOR?UPDATE;
BEGIN
???OPEN?c1;
???LOOP
??????FETCH?c1?INTO?v_emp_record;
??????EXIT?WHEN?c1%NOTFOUND;
??????IF?v_emp_record.department_id?=?90?AND
?????????v_emp_record.job_id?=?'AD_VP'
??????THEN
?????????UPDATE?employees?SET?salary?=?20000
?????????WHERE?CURRENT?OF?c1;??--更新當前游標行對應的數據行
??????END?IF;
???END?LOOP;
???COMMIT;???--提交已經修改的數據
???CLOSE?c1;
END;

4.2?游標變量

與游標一樣,游標變量也是一個指向多行查詢結果集合中當前數據行的指針。但與游標不同的是,游標變量是動態的,而游標是靜態的。游標只能與指定的查詢相連,即固定指向一個查詢的內存處理區域,而游標變量則可與不同的查詢語句相連,它可以指向不同查詢語句的內存處理區域(但不能同時指向多個內存處理區域,在某一時刻只能與一個查詢語句相連),只要這些查詢語句的返回類型兼容即可。

4.2.1??聲明游標變量

游標變量為一個指針,它屬于參照類型,所以在聲明游標變量類型之前必須先定義游標變量類型。在PL/SQL中,可以在塊、子程序和包的聲明區域內定義游標變量類型。

語法格式為:

TYPE?ref_type_name?IS?REF?CURSOR
?[?RETURN?return_type];

其中:ref_type_name為新定義的游標變量類型名稱;

??return_type?為游標變量的返回值類型,它必須為記錄變量。

在定義游標變量類型時,可以采用強類型定義和弱類型定義兩種。強類型定義必須指定游標變量的返回值類型,而弱類型定義則不說明返回值類型。

聲明一個游標變量的兩個步驟:

步驟一:定義一個REF?CURSOU數據類型,如:

TYPE?ref_cursor_type?IS?REF?CURSOR;

步驟二:聲明一個該數據類型的游標變量,如:

cv_ref?REF_CURSOR_TYPE;

例:創建兩個強類型定義游標變量和一個弱類型游標變量:

DECLARE
????TYPE?deptrecord?IS?RECORD(
????????Deptno?departments.department_id%TYPE,
????????Dname?departments.department_name%TYPE,
????????Loc?departments.location_id%TYPE
????);
????TYPE?deptcurtype?IS?REF?CURSOR?RETURN?departments%ROWTYPE;
????TYPE?deptcurtyp1?IS?REF?CURSOR?RETURN?deptrecord;
????TYPE?curtype?IS?REF?CURSOR;
????Dept_c1?deptcurtype;
????Dept_c2?deptcurtyp1;
????Cv?curtype;

4.2.2??游標變量操作

與游標一樣,游標變量操作也包括打開、提取和關閉三個步驟。

1.?打開游標變量

打開游標變量時使用的是OPEN…FOR?語句。格式為:

OPEN?{cursor_variable_name?|?:host_cursor_variable_name}
FOR?select_statement;

其中:cursor_variable_name為游標變量,host_cursor_variable_name為PL/SQL主機環境(如OCI:?ORACLE?Call?Interface,Pro*c?程序等)中聲明的游標變量。

OPEN…FOR?語句可以在關閉當前的游標變量之前重新打開游標變量,而不會導致CURSOR_ALREAD_OPEN異常錯誤。新打開游標變量時,前一個查詢的內存處理區將被釋放。

2.?提取游標變量數據

使用FETCH語句提取游標變量結果集合中的數據。格式為:

FETCH?{cursor_variable_name?|?:host_cursor_variable_name}
INTO?{variable?[,?variable]…|?record_variable};

其中:cursor_variable_name和host_cursor_variable_name分別為游標變量和宿主游標變量名稱;variable和record_variable分別為普通變量和記錄變量名稱。

3.?關閉游標變量

CLOSE語句關閉游標變量,格式為:

CLOSE?{cursor_variable_name?|?:host_cursor_variable_name}

其中:cursor_variable_name和host_cursor_variable_name分別為游標變量和宿主游標變量名稱,如果應用程序試圖關閉一個未打開的游標變量,則將導致INVALID_CURSOR異常錯誤。

例15:強類型參照游標變量類型

DECLARE
????TYPE?emp_job_rec?IS?RECORD(
????????Employee_id?employees.employee_id%TYPE,
????????Employee_name?employees.first_name%TYPE,
????????Job_title?employees.job_id%TYPE
????);
????TYPE?emp_job_refcur_type?IS?REF?CURSOR?RETURN?emp_job_rec;
????Emp_refcur?emp_job_refcur_type?;
????Emp_job?emp_job_rec;
BEGIN
????OPEN?emp_refcur?FOR?
????SELECT?employees.employee_id,?employees.first_name||employees.last_name,?employees.job_id?
??FROM?employees?
??ORDER?BY?employees.department_id;
????FETCH?emp_refcur?INTO?emp_job;
????WHILE?emp_refcur%FOUND?LOOP
???????DBMS_OUTPUT.PUT_LINE(emp_job.employee_id||':?'||emp_job.employee_name||'?is?a?'||emp_job.job_title);
????FETCH?emp_refcur?INTO?emp_job;
????END?LOOP;
END;

例16:弱類型參照游標變量類型

PROMPT
PROMPT?'What?table?would?you?like?to?see?'
ACCEPT?tab?PROMPT?'(D)epartment,?or?(E)mployees:'
DECLARE
????Type?refcur_t?IS?REF?CURSOR;
????Refcur?refcur_t;
????TYPE?sample_rec_type?IS?RECORD?(
????????Id?number,
????????Description?VARCHAR2?(30)
????);
????sample?sample_rec_type;
????selection?varchar2(1)?:=?UPPER?(SUBSTR?('&tab',?1,?1));
BEGIN
????IF?selection='D'?THEN
????????OPEN?refcur?FOR?
????SELECT?departments.department_id,?departments.department_name?FROM?departments;
????????DBMS_OUTPUT.PUT_LINE('Department?data');
????ELSIF?selection='E'?THEN
????????OPEN?refcur?FOR?
????SELECT?employees.employee_id,?employees.first_name||'?is?a?'||employees.job_id?FROM?employees;
????????DBMS_OUTPUT.PUT_LINE('Employee?data');
????ELSE
????????DBMS_OUTPUT.PUT_LINE('Please?enter?''D''?or?''E''');
????????RETURN;
????END?IF;
????DBMS_OUTPUT.PUT_LINE('----------------------');
????FETCH?refcur?INTO?sample;
????WHILE?refcur%FOUND?LOOP
????????DBMS_OUTPUT.PUT_LINE(sample.id||':?'||sample.description);
????????FETCH?refcur?INTO?sample;
????END?LOOP;
????CLOSE?refcur;
END;

例17:使用游標變量(沒有RETURN子句)

DECLARE
--定義一個游標數據類型
???TYPE?emp_cursor_type?IS?REF?CURSOR;
--聲明一個游標變量
???c1?EMP_CURSOR_TYPE;
--聲明兩個記錄變量
???v_emp_record?employees%ROWTYPE;
???v_reg_record?regions%ROWTYPE;
BEGIN
???OPEN?c1?FOR?SELECT?*?FROM?employees?WHERE?department_id?=?20;
???LOOP
??????FETCH?c1?INTO?v_emp_record;
??????EXIT?WHEN?c1%NOTFOUND;
??????DBMS_OUTPUT.PUT_LINE(v_emp_record.first_name||'的雇傭日期是'
????????????????????????????||v_emp_record.hire_date);
???END?LOOP;
--將同一個游標變量對應到另一個SELECT語句
???OPEN?c1?FOR?SELECT?*?FROM?regions?WHERE?region_id?IN(1,2);
???LOOP
??????FETCH?c1?INTO?v_reg_record;
??????EXIT?WHEN?c1%NOTFOUND;
??????DBMS_OUTPUT.PUT_LINE(v_reg_record.region_id||'表示'
????????????????????????????||v_reg_record.region_name);
???END?LOOP;
???CLOSE?c1;
END;

例18:使用游標變量(有RETURN子句)

DECLARE
--定義一個與employees表中的這幾個列相同的記錄數據類型
???TYPE?emp_record_type?IS?RECORD(
????????f_name???employees.first_name%TYPE,
????????h_date???employees.hire_date%TYPE,
????????j_id?????employees.job_id%TYPE);
--聲明一個該記錄數據類型的記錄變量
???v_emp_record?EMP_RECORD_TYPE;
--定義一個游標數據類型
???TYPE?emp_cursor_type?IS?REF?CURSOR
????????RETURN?EMP_RECORD_TYPE;
--聲明一個游標變量
???c1?EMP_CURSOR_TYPE;
BEGIN
???OPEN?c1?FOR?SELECT?first_name,?hire_date,?job_id
???????????????FROM?employees?WHERE?department_id?=?20;
???LOOP
??????FETCH?c1?INTO?v_emp_record;
??????EXIT?WHEN?c1%NOTFOUND;
??????DBMS_OUTPUT.PUT_LINE('雇員名稱:'||v_emp_record.f_name
????????????????||'??雇傭日期:'||v_emp_record.h_date
????????????????||'??崗位:'||v_emp_record.j_id);
???END?LOOP;
???CLOSE?c1;
END;

cnBlobs:http://www.cnblogs.com/huyong/

總結

以上是生活随笔為你收集整理的Oracle 把游标说透的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

国产一区视频导航 | 99久高清在线观看视频99精品热在线观看视频 | 日韩69av| 国产手机av在线 | 欧美一区免费观看 | 日本最新中文字幕 | 色天天综合久久久久综合片 | 黄色a视频免费 | 午夜精品久久久久久久99无限制 | www.久久色.com| 91插插影库 | 97精品国产91久久久久久 | 日韩欧美有码在线 | 99视频久久 | 亚州精品视频 | 免费在线播放 | 成人性生爱a∨ | 亚洲天天摸日日摸天天欢 | 最新成人在线 | 91精品国产麻豆国产自产影视 | 91激情视频在线播放 | 992tv人人网tv亚洲精品 | 久久免费精品一区二区三区 | 久久国产精品成人免费浪潮 | 99爱国产精品| 91福利视频一区 | 激情久久久 | 免费看的黄色的网站 | 九九色视频 | 亚洲精品理论片 | 在线国产精品一区 | 亚洲黄色成人 | 在线观看涩涩 | 国产精品永久久久久久久www | 国产自产高清不卡 | 天堂在线一区二区 | 毛片激情永久免费 | 国产精品久久久久久久久久直播 | 日日操天天操狠狠操 | 日韩一区二区三区观看 | 日韩欧美一区二区三区视频 | 国产日韩中文字幕 | 69av在线播放 | 日韩大片在线免费观看 | 亚洲国产久| 狠狠躁日日躁狂躁夜夜躁av | 国产精品久久久久久久久久白浆 | 欧美性做爰猛烈叫床潮 | 久草爱视频| 久久久久免费看 | av线上免费观看 | 日韩成人中文字幕 | 三上悠亚一区二区在线观看 | 精品女同一区二区三区在线观看 | 久草免费新视频 | 亚洲一级久久 | 天天摸夜夜添 | 波多野结衣资源 | 成人免费av电影 | 久久久高清一区二区三区 | 91精品欧美 | 日韩精品一区二区在线 | 岛国一区在线 | 五月婷婷中文 | 亚洲一区二区精品视频 | 国产精品一区在线观看你懂的 | 男女男视频 | 久久草网站 | 天天综合婷婷 | 干天天 | 丁香综合五月 | 日韩电影精品 | 精品成人久久 | 看片一区二区三区 | 国产99久久久久久免费看 | 91人人插| 国产成人精品一区二区三区 | 国产小视频在线看 | 欧美老女人xx | 中文字幕欧美激情 | 日日夜夜免费精品 | 国产精品亚洲片在线播放 | 精品国产视频在线 | 国产精品欧美在线 | 欧美日韩免费一区二区三区 | 色99色 | aaa日本高清在线播放免费观看 | 国产在线播放不卡 | 亚洲欧美成aⅴ人在线观看 四虎在线观看 | 亚洲国产欧美在线人成大黄瓜 | 婷婷视频在线观看 | 美女久久久久久久久久久 | 免费福利视频导航 | 99久久精品国产一区二区三区 | 国产一区二区高清视频 | 精品亚洲欧美一区 | 五月婷婷操 | 天天草天天干天天射 | 激情综合色综合久久 | 欧美坐爱视频 | 亚洲精品午夜久久久久久久久久久 | 五月天视频网 | 国产精品资源在线观看 | 免费视频在线观看网站 | 久久久久成人精品 | 五月婷婷.com | 四虎影视成人永久免费观看亚洲欧美 | 免费在线观看av网址 | 精品亚洲成人 | 黄色片软件网站 | 国产精品视频久久 | 国产又黄又爽无遮挡 | 在线av资源 | 国产精品国产精品 | 久久精品视频在线看 | 婷婷精品在线视频 | www久久99 | 欧美日韩一二三四区 | 欧美va电影| 中文字幕在线一区观看 | a黄在线观看 | 欧美日韩国产色综合一二三四 | 久久精品日韩 | 碰超在线观看 | 国产日韩视频在线播放 | 狠狠干夜夜 | 精品你懂的 | 国产资源在线视频 | 国产日韩视频在线播放 | 91精品国自产在线偷拍蜜桃 | 香蕉精品视频在线观看 | 久久久久久福利 | 亚洲成人av免费 | 午夜精品一区二区三区在线 | 91精品在线麻豆 | 伊人久久在线观看 | 婷婷亚洲综合五月天小说 | 精品日韩在线一区 | 在线日韩av | 天天综合亚洲 | 中文字幕在线观看完整版电影 | 精品99在线 | 色在线中文字幕 | 蜜臀精品久久久久久蜜臀 | 久久人人艹 | 欧美激情视频在线免费观看 | 91九色精品 | 久久你懂的 | 99精品视频免费观看视频 | 久久久久久久久毛片 | 欧美色综合久久 | 久久久久国产成人免费精品免费 | 免费激情在线电影 | 成人免费看黄 | 亚洲aⅴ乱码精品成人区 | 涩涩网站在线观看 | 欧美孕妇视频 | 亚洲无毛专区 | 色婷婷免费视频 | 日韩欧美99 | 日b黄色片 | 久久久久日本精品一区二区三区 | 久久久午夜影院 | 欧美一二三视频 | 久久久国产一区二区三区 | 91久久一区二区 | 久久久免费看视频 | 97超碰免费在线 | 人人爽人人干 | 91亚洲精品久久久 | 91精品免费| 在线观看久久 | av资源免费在线观看 | 成人免费视频播放 | 黄色小说免费观看 | 国产午夜影院 | 97av影院 | 日韩欧美精品在线 | 日韩欧美专区 | 99r国产精品 | 97高清视频 | 9999国产精品 | 丁香亚洲 | 日日操天天操夜夜操 | 日韩一区二区免费播放 | 在线播放一区二区三区 | 国产高清免费视频 | 亚洲第一区在线播放 | 亚洲香蕉视频 | 成人午夜网址 | 久久人人爽人人爽人人 | 天天干天天怕 | 久草电影在线观看 | 日韩福利在线观看 | 国产精品淫 | 不卡视频在线 | 欧美精品乱码99久久影院 | 四虎国产精品成人免费影视 | 高清一区二区三区av | 国色天香永久免费 | 日韩精品一区二区三区免费观看 | 狠狠狠狠狠狠狠狠 | 91毛片在线| av解说在线 | 日韩欧美在线免费观看 | 亚洲精品18日本一区app | 一区二区观看 | 精品国精品自拍自在线 | 欧美精品少妇xxxxx喷水 | 九色精品在线 | 日日夜夜噜 | 久久草在线精品 | 亚洲涩涩网 | 久久九九久久 | 亚洲国产精品成人女人久久 | 最新免费av在线 | av成人免费观看 | 涩涩爱夜夜爱 | 中文字幕色网站 | 久久久久久久综合色一本 | 综合国产视频 | 超碰97免费在线 | 五月天电影免费在线观看一区 | 国产精品免费一区二区 | 国产黄a三级三级三级三级三级 | 欧美日韩亚洲在线观看 | 天堂资源在线观看视频 | 狠狠色噜噜狠狠狠合久 | 五月婷婷综合激情 | 国产a网站| 亚洲视频 中文字幕 | 九九九毛片 | 久久人人干 | 亚洲精品视频免费在线观看 | 天天操天天摸天天爽 | 一级黄色大片 | www.com久久久 | 日日天天av| 欧美俄罗斯性视频 | 欧美精彩视频在线观看 | 最近中文字幕免费大全 | 国产高清亚洲 | 日本精品在线视频 | 一级黄色片在线播放 | 黄污在线看 | 欧美三级高清 | 亚洲国产影院av久久久久 | 色诱亚洲精品久久久久久 | 国产中文字幕在线视频 | 免费看片网页 | 黄色一区二区在线观看 | 午夜av大片 | 成人av免费 | 国产不卡av在线播放 | 亚洲免费av网站 | 日日干狠狠操 | 精品国产三级a∨在线欧美 免费一级片在线观看 | 最新国产精品亚洲 | 玖玖999| 成人免费大片黄在线播放 | 国产手机在线观看视频 | 成人免费在线观看电影 | 国精产品999国精产品岳 | 国产午夜精品在线 | 久久久久久久久精 | 91成人在线观看高潮 | 91黄在线看| 国产精品麻豆视频 | 亚洲成a人片77777潘金莲 | 亚洲精品高清视频在线观看 | 国产一区二区在线精品 | 色综久久 | 日本大尺码专区mv | 亚洲视频综合在线 | 亚洲 中文 欧美 日韩vr 在线 | 中文字幕在线观看视频网站 | 久久高清片 | 国产在线观看网站 | 一区二区三区免费播放 | 国产成人精品一区二区三区免费 | 99免费观看视频 | 国产一区在线看 | 中文字幕av全部资源www中文字幕在线观看 | 久久99精品久久久久久久久久久久 | 97人人网 | 久久精品高清视频 | 亚洲综合成人在线 | 色资源二区在线视频 | 国产精品 中文在线 | 久草在线视频网站 | 天天色天天操综合网 | 日日夜夜狠狠 | 精品久久一区二区 | 99精品99| 日韩最新中文字幕 | 国产自产在线视频 | 97免费| 日日夜夜网 | 久久久久久福利 | 美国人与动物xxxx | 伊人伊成久久人综合网站 | 日韩综合色 | 久久看片 | 91精品视频免费观看 | 久久久www | 狠狠干天天干 | 国产又黄又硬又爽 | 97超碰精品| 亚洲精品av在线 | 91精品久 | 天天操天天添天天吹 | 正在播放五月婷婷狠狠干 | 麻豆久久久久 | 国产精品1000 | 午夜国产在线 | 又黄又爽又刺激的视频 | 日韩黄色一区 | av色图天堂网 | 不卡av在线| 久久综合国产伦精品免费 | 欧美国产日韩久久 | 亚洲va在线va天堂 | 久久手机看片 | 久久久久久久久久久高潮一区二区 | 综合国产在线观看 | 国内揄拍国内精品 | 久久久亚洲精品 | 毛片在线播放网址 | 91在线播放视频 | 超碰在线观看av | 欧美色综合 | www.狠狠| 日韩欧美高清一区二区三区 | 欧美亚洲另类在线视频 | 一区二区三区在线观看免费视频 | 98福利在线| 综合国产视频 | 6699私人影院 | 国产精品麻豆视频 | 丁香六月中文字幕 | 国产精品久99 | 亚洲精品综合一二三区在线观看 | 911香蕉 | 亚洲特级毛片 | 欧美成人亚洲 | 日韩免费成人 | 久久涩视频 | 国产亚洲精品久 | 成 人 黄 色视频免费播放 | 久操中文字幕在线观看 | 91大神免费在线观看 | 久久精品96 | 中文字幕一区二区三区视频 | 特级毛片在线 | 免费看黄在线网站 | 99久久精品午夜一区二区小说 | 久久久久久蜜av免费网站 | 国产中文字幕视频在线 | 久久久精品一区二区三区 | 久久99亚洲网美利坚合众国 | 日韩mv欧美mv国产精品 | 奇米先锋 | 久久久观看 | av短片在线观看 | 在线观看中文 | 射久久 | 久久国产精品99久久久久久丝袜 | 久久超碰免费 | www国产亚洲精品久久网站 | 中文字幕成人一区 | 久草视频在线看 | 亚洲最快最全在线视频 | 欧美一级裸体视频 | 日本精品一区二区 | www.看片网站 | 麻豆91在线播放 | 久草在线一免费新视频 | 国产精品日韩久久久久 | 成人av亚洲 | av在线激情 | 亚洲成人一二三 | 深夜免费福利 | 久草视频手机在线 | 精品国产理论片 | 欧美福利视频一区 | 亚洲自拍偷拍色图 | av一区二区三区在线 | 精品一区二区三区香蕉蜜桃 | 99国产成+人+综合+亚洲 欧美 | 久久黄色片 | 久久成人久久 | 五月天久久久 | 丁香五婷 | 成人在线视频免费看 | 在线观看日韩 | 欧美国产日韩在线视频 | 成人影音在线 | 美女啪啪图片 | 色妞久久福利网 | www.婷婷com| 中文字幕日本在线 | 久久久久高清毛片一级 | 久久成人高清视频 | 亚洲日本中文字幕在线观看 | 国产高清不卡一区二区三区 | 亚洲精品女人 | 成年人黄色免费看 | 日韩av一卡二卡三卡 | 日韩理论电影在线观看 | 成人影视免费看 | 在线国产日本 | 亚洲精品国偷拍自产在线观看蜜桃 | 97夜夜澡人人爽人人免费 | japanesefreesexvideo高潮 | 精品久久久久久久久中文字幕 | 18国产精品福利片久久婷 | 精品国产美女在线 | 婷婷色5月| 欧美一级片免费观看 | 一二三区在线 | 中文字幕在线播放视频 | 国产精品久久久久久五月尺 | 亚洲成人家庭影院 | 在线免费91| 久久国产二区 | 日韩欧美久久 | 国产人成一区二区三区影院 | 在线免费中文字幕 | 中文字幕亚洲综合久久五月天色无吗'' | 96国产在线| 国产三级精品在线 | 久草在线欧美 | 精品国产99国产精品 | 伊人狠狠干 | 成人av中文字幕在线观看 | 一二三区视频在线 | 日日色综合 | 国产精品久久久久婷婷二区次 | 国产免码va在线观看免费 | 丁香视频| 色婷婷在线播放 | 丝袜美腿亚洲综合 | 五月婷婷免费 | 九色在线| 日韩精品一区二区三区电影 | 久久久精品影视 | 亚洲精品久久久久中文字幕二区 | 91人人爱 | 国产成人精品一区二区三区福利 | 人人插人人玩 | 国产精品男女 | 国产看片 色 | 日韩欧美视频在线观看免费 | 国内视频1区 | 欧美精品网站 | 永久免费精品视频网站 | 国产精品二区在线 | 久久人人97超碰精品888 | a在线观看国产 | 婷婷在线综合 | 一级黄色片在线播放 | 日韩av电影手机在线观看 | 看av免费 | av高清一区二区三区 | 最近日本mv字幕免费观看 | 国产一级久久久 | 国产又粗又猛又爽 | 99精品国产99久久久久久97 | 国产免费区 | 久久在线精品视频 | 高清免费在线视频 | 四虎成人精品在永久免费 | 久草在线最新免费 | 96精品高清视频在线观看软件特色 | 久久综合九色综合97婷婷女人 | 国产永久免费高清在线观看视频 | 中文字幕在线观看网 | 麻豆观看| 亚洲九九精品 | 国产三级久久久 | 久久精品成人欧美大片古装 | 色偷偷88888欧美精品久久 | 狠狠躁夜夜躁人人爽超碰91 | 中文字幕在线中文 | 视频一区久久 | 欧美日韩国产精品一区二区三区 | 国产精品嫩草69影院 | 国产精品丝袜在线 | 色婷婷综合久久久久中文字幕1 | 99久久999久久久精玫瑰 | 国产伦理一区二区 | 黄色大片av | 日韩成人黄色av | 亚洲成人在线免费 | 成人一级影视 | 一区二区三区www | 中文字幕一区二区三区乱码不卡 | 香蕉视频在线网站 | 欧美超碰在线 | a视频免费看 | 欧美日本在线视频 | 久久蜜臀一区二区三区av | 久久久久久久久久久国产精品 | av片中文字幕| 日韩在线免费小视频 | 国产91成人在在线播放 | 成人永久免费 | 国产一级在线看 | 激情av五月婷婷 | 天天操天天艹 | 国产精品99久久免费观看 | 伊人www22综合色 | 国产精品毛片久久久 | 亚洲免费av电影 | 国产日韩精品欧美 | 91爱爱视频 | 精品黄色片 | 中文字幕精品www乱入免费视频 | 日韩网站中文字幕 | 国产 日韩 欧美 在线 | av黄色一级片 | 日韩电影一区二区在线 | 国产成人av在线影院 | 日韩网站中文字幕 | 亚洲成人av片在线观看 | 国内免费久久久久久久久久久 | 99色视频在线 | 狠狠做六月爱婷婷综合aⅴ 日本高清免费中文字幕 | 亚洲九九九在线观看 | 亚洲理论视频 | 国产午夜麻豆影院在线观看 | 91av网站在线观看 | 欧美日韩二区在线 | 免费看片成人 | 91丨九色丨91啦蝌蚪老版 | 亚洲人成人99网站 | www.看片网站 | 中文字幕亚洲精品在线观看 | 国产精品刺激对白麻豆99 | 精品国产中文字幕 | 久久在线免费 | 69精品久久 | 中文字幕一区在线观看视频 | 婷婷夜夜 | 在线播放国产精品 | 国产精品久久久久久久久久尿 | 99热精品国产 | 亚洲精品国精品久久99热 | 成人99免费视频 | 91在线视频观看免费 | 久久影视精品 | 天天综合网 天天 | 国产91精品久久久久 | 蜜臀久久99精品久久久无需会员 | 五月婷婷导航 | 亚洲精品h | 亚洲精品乱码久久久久久蜜桃动漫 | 在线观看视频一区二区三区 | 国产一级精品视频 | 九九精品毛片 | 伊人资源站 | 欧美九九九| 激情五月综合 | 18性欧美xxxⅹ性满足 | 久久精品伊人 | 中文字幕一二 | 国产91欧美| 韩日视频在线 | 激情综合五月天 | 天天干天天干天天干天天干天天干天天干 | 国产手机在线精品 | 亚洲午夜精品福利 | 伊人影院在线观看 | 亚洲精品在线观看的 | 日韩精品一区二区三区视频播放 | 丁香六月天 | 成片视频在线观看 | 美女免费电影 | 伊人开心激情 | 国语精品免费视频 | 91视频在线国产 | 国产v亚洲v| 中文字幕第一页在线 | 久久亚洲精品国产亚洲老地址 | 国产又粗又硬又长又爽的视频 | 亚洲一区视频免费观看 | 免费看色的网站 | 日韩电影在线观看一区 | 日韩av视屏在线观看 | 亚洲专区中文字幕 | 不卡视频在线 | 久草视频在线播放 | 国产视频久 | 日韩一级片观看 | 亚洲激情综合网 | 97操操| 欧洲精品二区 | 国产在线无 | 91看片在线免费观看 | 成年人在线免费看视频 | 亚洲一级片在线观看 | 国产午夜精品av一区二区 | 六月丁香在线视频 | 96精品视频| 免费激情在线电影 | 亚洲国产操 | 久久8| 香蕉视频在线观看免费 | 久久这里有精品 | 午夜精品久久久久99热app | 人人狠狠综合久久亚洲婷 | 在线观av| 亚洲一区二区视频在线播放 | 久久人人爽人人爽人人片av软件 | 韩国精品福利一区二区三区 | 亚洲黄色免费在线看 | 91久久久久久久一区二区 | 国产一区二区在线免费观看 | 91麻豆国产 | 国产成人99久久亚洲综合精品 | 中文字幕色婷婷在线视频 | 亚洲综合视频网 | 香蕉在线观看 | 国产成人精品国内自产拍免费看 | 国内精品久久久久 | 91精品久久久久久粉嫩 | 五月情婷婷 | 日本最新中文字幕 | 久久久国产精品视频 | 久久久人人人 | 午夜精品久久久久久久99水蜜桃 | 欧美国产精品一区二区 | 成人资源在线观看 | 午夜精品久久久久99热app | 国产精品免费看久久久8精臀av | 免费观看性生交 | 欧美a√在线 | 在线观看黄色的网站 | 特级黄录像视频 | 九九热视频在线播放 | 久久久久在线观看 | 一区二区视频在线播放 | 日韩免费在线视频 | 99精品一级欧美片免费播放 | 国产又粗又猛又黄又爽视频 | 韩国三级在线一区 | 久久久久久久综合色一本 | www.夜夜夜 | 日韩免费在线视频 | 国产91在线免费视频 | 中文字幕丰满人伦在线 | 国产无吗一区二区三区在线欢 | 久久国产一二区 | 久草视频在线免费播放 | 久草在线一免费新视频 | 国产高清免费av | 国产一级精品在线观看 | 免费美女久久99 | 日韩欧美精品一区二区三区经典 | 视频成人永久免费视频 | 亚洲成人资源 | 国产精品乱码在线 | 精品天堂av | 久久久五月婷婷 | 草久在线视频 | 天天伊人狠狠 | 久操中文字幕在线观看 | 成人一级影视 | 天天综合网国产 | 99视频+国产日韩欧美 | 欧美福利在线播放 | 日本护士撒尿xxxx18 | 国产 日韩 在线 亚洲 字幕 中文 | 这里只有精彩视频 | 夜夜夜夜猛噜噜噜噜噜初音未来 | 久久久美女 | 99视频+国产日韩欧美 | 激情深爱五月 | 久久久国产精品成人免费 | 在线观看国产永久免费视频 | free,性欧美 九九交易行官网 | 一本一本久久a久久精品综合妖精 | 中文字幕亚洲精品在线观看 | 最近中文字幕免费视频 | 99久久999久久久精玫瑰 | 免费av观看 | 在线免费av播放 | 天天摸天天舔 | 精品视频 | 亚洲精品午夜国产va久久成人 | 射久久| 在线三级播放 | 欧美在线观看视频一区二区三区 | 亚洲激情六月 | 亚洲人成免费网站 | 97国产| 亚洲 欧美 国产 va在线影院 | 91麻豆看国产在线紧急地址 | 久草电影在线观看 | 国产精品乱码久久久久久1区2区 | 亚洲成年人免费网站 | 色人久久 | 9999免费视频 | 亚洲2019精品| 99精品在线免费在线观看 | 国产黄色美女 | 国产精品久久电影观看 | 久久久久国产精品免费网站 | 97在线观看视频国产 | 日韩色在线观看 | 黄色成年网站 | 99视频精品全部免费 在线 | 国产一区高清在线 | 久久久久久久久爱 | 国产成人精品一区二区在线 | 天堂av在线免费观看 | 91高清免费看 | 色噜噜狠狠色综合中国 | 国产精品日韩久久久久 | 欧美一二三区在线播放 | 久久久人人爽 | 日韩电影久久久 | 99视| 亚洲激情校园春色 | 叶爱av在线 | 亚洲精色 | 国产成人在线看 | 亚洲激情六月 | 成人免费91 | 久久午夜电影 | 国产91亚洲 | 欧美a级在线免费观看 | 久久九九久久九九 | 国产精品 9999 | 夜夜视频 | 豆豆色资源网xfplay | 国产精品久久一区二区三区不卡 | 欧美性生爱 | 色成人亚洲 | 成人黄色一级视频 | 国内视频在线 | 国产精成人品免费观看 | 精品99999| 97精品久久人人爽人人爽 | 国产视频一级 | 四季av综合网站 | 97超碰超碰久久福利超碰 | 亚洲播放一区 | 色婷婷av在线 | 国内精品久久久久久久97牛牛 | 狠狠色伊人亚洲综合网站色 | 国产精彩视频一区二区 | 欧美一二三区在线播放 | 91传媒在线 | 日韩精品欧美专区 | 成人av手机在线 | av女优中文字幕在线观看 | 91日韩在线 | 国产精品久久电影观看 | 99国产精品久久久久老师 | 亚洲一片黄| 91免费版在线观看 | 精品久久一 | 久草网免费 | 99热.com | 91成人精品一区在线播放69 | 91精品视频在线看 | 99热99re6国产在线播放 | 国产精品99久久久久久有的能看 | 免费合欢视频成人app | 97在线观看视频国产 | 久久国产亚洲精品 | 中文字幕一区二区三区四区视频 | 国产91粉嫩白浆在线观看 | 亚洲少妇自拍 | 欧美国产精品一区二区 | 亚洲一级特黄 | 高清不卡一区二区在线 | 91av网址| 国产精品一区二区吃奶在线观看 | 婷婷六月天天 | 国产一二区精品 | 精品九九九九 | 国产在线免费观看 | 97视频在线观看播放 | 国产99亚洲 | 6080yy午夜一二三区久久 | 欧美激情视频在线免费观看 | 伊人色播 | 天天玩天天干天天操 | 五月亚洲综合 | 99久久久国产精品免费99 | 国产男女无遮挡猛进猛出在线观看 | 国产精品永久久久久久久www | 日本中文一级片 | 色5月婷婷 | 国产精品丝袜久久久久久久不卡 | 1024手机看片国产 | 中文字幕在线观看你懂的 | 成人性生交大片免费看中文网站 | 久久久久久久久久久久久国产精品 | 超碰97公开 | 国产日韩欧美自拍 | 91av在线免费看 | 国产直播av | 欧美日韩国产在线 | 亚洲精品国产精品乱码在线观看 | www.色婷婷.com | 欧美做受xxx | 射射射av | 日本黄色免费网站 | 91免费高清视频 | 在线看中文字幕 | 天天操天 | 中文字幕亚洲不卡 | 国产日韩在线看 | 天天操天天干天天操天天干 | 一级免费看 | 99久久精品免费 | 久久综合狠狠综合久久狠狠色综合 | 99精品国产免费久久久久久下载 | 激情开心网站 | 99精品在线视频播放 | 91热爆在线观看 | 综合网伊人 | av中文字幕在线播放 | 欧美视频二区 | 日韩视频在线不卡 | 成 人 黄 色 片 在线播放 | 国产一区影院 | 日韩一级电影在线观看 | 久久中文精品视频 | 久久小视频 | 国产一级大片在线观看 | 日日夜夜免费精品视频 | 亚洲精品一区二区三区在线观看 | 99看视频在线观看 | 国产精品区在线观看 | 激情综合婷婷 | 成年在线观看 | 欧美日韩国产一区二区三区在线观看 | 国产精品久久久久久久久久久久久 | 欧美9999| 久久久久国产成人免费精品免费 | 日韩久久精品一区二区三区 | 国产麻豆电影在线观看 | 久久久久久久99 | 看v片 | 深爱开心激情 | 久久久久黄色 | 久久手机在线视频 | 91麻豆精品国产午夜天堂 | 亚洲国产中文字幕在线观看 | 精品一区中文字幕 | 日韩在线视频国产 | 精品视频久久久久久 | 国产黄色成人av | 亚洲精品91天天久久人人 | 人人爱爱人人 | 最新午夜 | 国产精品99久久久久久宅男 | 免费观看全黄做爰大片国产 | 婷婷5月激情5月 | 一区二区三区在线观看免费视频 | 日韩黄色一区 | av片一区| 国产真实在线 | 国产精品va在线观看入 | 久久久久久久久久久久国产精品 | 欧美福利精品 | 日韩av影视在线 | 激情电影影院 | 色婷婷狠狠五月综合天色拍 | 亚洲精品白浆高清久久久久久 | 久久视影| 在线观看91 | 九九爱免费视频在线观看 | 久久精品免费观看 | 国产 日韩 中文字幕 | 久久久久成人精品亚洲国产 | 日韩在线观看第一页 | 国内偷拍精品视频 | 福利视频精品 | 色婷婷a| 一区二区三区精品在线 | 日韩免费看 | 99视频精品在线 | 中文字幕资源在线观看 | 最近免费观看的电影完整版 | 国产精品毛片完整版 | 中文字幕av电影下载 | 中文字幕在线高清 | av成人免费在线看 | 精品美女久久久久 | 国产视频一级 | www.国产精品| 国产最顶级的黄色片在线免费观看 | 91av在线电影| 国产99一区视频免费 | 国产精品久久久久久久久久久久久 | 国产一级免费片 | 久久视频精品 | 懂色av一区二区在线播放 | 人人插人人看 | 久久免费的精品国产v∧ | 97在线免费观看 | 国产黄色免费 | 99视频在线免费播放 | 天天综合天天综合 | 91久久精| 中文字幕在线看视频国产中文版 | 成人免费观看在线视频 | 日韩免费福利 | 成人性生交视频 | 色综合久久久久 | 看国产黄色片 | 91在线精品播放 | 在线观看免费版高清版 | 欧美日韩在线视频一区二区 | 国产精品女同一区二区三区久久夜 | 国产日韩三级 | 日韩美女免费线视频 | 91麻豆国产| 黄色av电影在线 | 99视频在线精品 | 国产精品久久久久一区二区 | 亚州国产精品 | 高清日韩一区二区 | 国产精品每日更新 | 天天操天天射天天爱 | 国产精品a成v人在线播放 | 久久久麻豆视频 | 日韩免费在线视频观看 | av字幕在线 | 久久久久欧美精品999 | 久久观看免费视频 | 美女av免费看 | 日韩高清不卡一区二区三区 | 中文字幕.av.在线 | 欧美日韩二三区 | 欧美视频xxx| 久久久www成人免费精品张筱雨 | 欧美日韩不卡一区二区 | 亚洲精品乱码久久久一二三 | 天天操天天添 | 最近字幕在线观看第一季 | a久久久久 | 久久电影日韩 | 97人人射 | 国产 在线 高清 精品 | 日本爱爱免费 | 日日夜色| 美国av大片 | 99热在线看 | 色综合久久综合网 | 欧美日韩精品在线一区二区 | 久久精品久久久精品美女 | 黄色a一级视频 | 亚洲美女在线一区 | 成人欧美一区二区三区在线观看 | 成人国产精品久久久 | 国产精品一区二区久久精品 | 91av网址 | 亚洲高清不卡av | 国产视频一区精品 | 在线亚洲精品 | 日韩av一区二区三区在线观看 | 欧美一区在线看 | 亚洲最新在线 | 久久中文网 | 国际精品久久久久 | 在线观看亚洲精品 | 99热网站| 成人免费av电影 | www.亚洲精品视频 | 国产理伦在线 | 国产精品久久久久久久久久ktv | 97韩国电影| 亚洲蜜桃av | 国产高h视频 | 九精品 | 国产偷国产偷亚洲清高 | 亚洲国产免费看 | 成人三级网站在线观看 | 97在线超碰| 免费激情网| 国产三级国产精品国产专区50 | 成人午夜影院在线观看 | 成年美女黄网站色大片免费看 | 国产视频一二三 | 国产在线色站 | 在线观看免费黄视频 | 狠狠色伊人亚洲综合成人 | 国产一级免费在线 | 天天干婷婷 | 久久欧洲视频 | 91日韩精品一区 | 日本字幕网 |