游標變量的使用


一 游標變量

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

 

1 聲明游標變量

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;

 

二 游標變量的操作

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

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異常錯誤。新打開游標變量時,前一個查詢的內存處理區將被釋放

 

提取游標變量數據

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

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

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

 

關閉游標變量

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

CLOSE {cursor_variable_name | :host_cursor_variable_name}

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

 

例子:

強類型參照游標變量類型

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;

 

弱類型參照游標變量類型

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;

 

使用游標變量(沒有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;

 

使用游標變量(有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;

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM