1. 程式人生 > >PLSQL遊標使用例項

PLSQL遊標使用例項

一、定義:

遊標:指向查詢結果集的指標,指向哪一行,提取哪一行的資料(PLSQL的遊標預設指向結果集的第一行)

遊標的四個屬性
遊標變數 %found: 當最近一次讀入記錄成功時返回true
遊標變數 %notfound:同上 相反
遊標變數 %isopen:判斷遊標是否已經開啟

遊標變數 %rowcount:返回已從遊標中讀取的記錄數

隱示遊標:固定名稱sql
遊標的四個屬性
SQL%FOUND:如果操作有影響行,就為true,否則為false
SQL%NOTFOUND :求反
SQL%ISOPEN:在隱示遊標中,取值永遠為false
SQL%ROWCOUNT:操作影響的行數

必須在事務結束之前讀取遊標屬性,只能讀取最近的一次DML操作的遊標狀態

二、使用步驟
使用遊標分為4個步驟
1,宣告遊標 cursor 遊標變數 is 查詢語句
2,開啟遊標 open 遊標變數(不能重複開啟遊標)
3,提取資料 fetch 遊標變數 into 變數1,變數2,.
4,關閉遊標釋放系統資源 close 遊標變數


請參考以下例項:

(1)查詢輸出所有員工的編號,姓名,工資|
DECLARE
    v_empid employees.employee_id%TYPE;
    v_name  employees.last_name%TYPE;         
    v_salary employees.salary%TYPE;
    

    CURSOR  emp_cursor IS
    SELECT  employee_id,last_name,salary
    FROM    employees
    WHERE   department_id = 90;
BEGIN
    OPEN    emp_cursor;
    FETCH   emp_cursor INTO v_empid ,v_name, v_salary;
    dbms_output.put_line('編號'|| v_empid);
    dbms_output.put_line('姓名'|| v_name);
    dbms_output.put_line('工資'|| v_salary);
    CLOSE emp_cursor;
END;

(2)查詢輸出所有員工的編號,姓名,工資
 

DECLARE
    v_empid employees.employee_id%TYPE;
    v_name employees.last_name%TYPE;
    v_salary employees.salary%TYPE;
    
    CURSOR emp_cursor IS
    SELECT employee_id,last_name,salary
    FROM employees
    WHERE department_id = 90;


BEGIN
    OPEN emp_cursor;
    FETCH  emp_cursor INTO v_empid ,v_name, v_salary;
    WHILE emp_cursor%FOUND LOOP
    dbms_output.put_line('編號'|| v_empid);
    dbms_output.put_line('姓名'|| v_name);
    dbms_output.put_line('工資'|| v_salary);
    dbms_output.put_line('-------------------');
    FETCH  emp_cursor INTO v_empid ,v_name, v_salary;
    END LOOP;
    CLOSE emp_cursor;
END;


(3)查詢輸出所有員工編號,姓名,工資(記錄型別)

DECLARE
    e employees%ROWTYPE;
    CURSOR emp_cursor IS
    SELECT *
    FROM employees;
BEGIN
     OPEN   emp_cursor;
      FETCH emp_cursor INTO e;
      WHILE emp_cursor%FOUND LOOP
      dbms_output.put_line('編號' || e.employee_id);
      dbms_output.put_line('姓名' || e.last_name);
      dbms_output.put_line('工資' || e.salary);
      dbms_output.put_line('職務' || e.job_id);
      dbms_output.put_line('入職日期' || e.hire_date);
      dbms_output.put_line('-----------------------');
      FETCH emp_cursor INTO e;
      END LOOP;
      CLOSE emp_cursor;
END;

(4)查詢輸出所有員工編號,姓名,工資(PLSQL表型別)

DECLARE
     TYPE emp_table_type IS TABLE OF employees%ROWTYPE INDEX BY BINARY_INTEGER;


     e emp_table_type;


    CURSOR emp_cursor IS
    SELECT * FROM employees;
BEGIN
    OPEN emp_cursor;
    FETCH emp_cursor BULK COLLECT
    INTO e;
    FOR i IN 1 .. e.count LOOP
    dbms_output.put_line('編號' || e(i).employee_id);
    dbms_output.put_line('姓名' || e(i).last_name);
    dbms_output.put_line('工資' || e(i).salary);
    dbms_output.put_line('----------------------------');
    END LOOP;
    CLOSE emp_cursor;
END;


(5)查詢輸出所有員工編號,姓名,工資(通過limit控制提取的資料量)


DECLARE
  TYPE emp_table_type IS TABLE OF employees%ROWTYPE
  INDEX BY BINARY_INTEGER;
  e emp_table_type;
  CURSOR emp_cursor IS
  SELECT * FROM employees;
BEGIN 
   OPEN emp_cursor;
   FETCH emp_cursor BULK COLLECT INTO e LIMIT 6 ;
   
   FOR i IN 1..e.count LOOP
    dbms_output.put_line('編號' || e(i).employee_id);
    dbms_output.put_line('姓名' || e(i).last_name);
    dbms_output.put_line('工資' || e(i).salary);
    dbms_output.put_line('----------------------------');
     END LOOP;
CLOSE emp_cursor;
END;


(6)查詢輸出某個部門的員工的編號,姓名,工資(引數化遊標)

DECLARE
  v_empid employees.employee_id%TYPE;
  v_name employees.last_name%TYPE;
  v_salary employees.salary%TYPE;
  CURSOR emp_cursor(p_deptid employees.employee_id%TYPE) IS
  SELECT employee_id,last_name,salary
  FROM employees
 WHERE department_id = p_deptid; 
BEGIN
   OPEN emp_cursor(60);
   LOOP 
   FETCH emp_cursor  INTO v_empid,v_name,v_salary ;
   EXIT WHEN emp_cursor%NOTFOUND;
   dbms_output.put_line('編號:'||v_empid||'姓名:'||v_name||'工資:'||v_salary);
   END LOOP;
  CLOSE emp_cursor;
  dbms_output.put_line('----------------------------');
  OPEN emp_cursor(50);
  LOOP
    FETCH emp_cursor  INTO v_empid,v_name,v_salary ;
    EXIT WHEN emp_cursor%NOTFOUND;
    dbms_output.put_line('編號:'||v_empid||'姓名:'||v_name||'工資:'||v_salary);
    END LOOP;
    CLOSE emp_cursor;
END;


(7)查詢輸出所有的員工編號,姓名,工資(遊標的for迴圈)

DECLARE
    CURSOR emp_cursor IS
    SELECT * 
    FROM employees;
BEGIN 
  FOR e IN emp_cursor LOOP
    dbms_output.put_line('編號:'||e.employee_id||'姓名:'||e.last_name||'工資:'||e.salary);
  END LOOP;
END;

(8)查詢輸出所有的員工編號,姓名,工資(帶引數)


DECLARE
    CURSOR emp_cursor(p_depid employees.employee_id%TYPE)IS
    SELECT * 
    FROM employees
    WHERE department_id=p_depid;
BEGIN 
  FOR e IN emp_cursor(50) LOOP
    dbms_output.put_line('編號:'||e.employee_id||'姓名:'||e.last_name||'工資:'||e.salary);
  END LOOP;
END;

(9)查詢輸出所有的員工編號,姓名,工資(最精簡的寫法)

DECLARE


BEGIN 
  FOR e IN (SELECT * FROM employees) LOOP
    dbms_output.put_line('編號:'||e.employee_id||'姓名:'||e.last_name||'工資:'||e.salary);
  END LOOP;


END;

(10)輸出每個部門的部門編號,部門名稱以及這個部門的下屬員工的編號,姓名,工資


DECLARE
      CURSOR dept_cursor IS
      SELECT * FROM departments;
      
      CURSOR emp_cursor(p_deptid NUMBER) IS
      SELECT * FROM employees
      WHERE department_id = p_deptid;
BEGIN 
     FOR d IN dept_cursor LOOP
     dbms_output.put_line(d.department_id|| '  '||d.department_name);
     FOR e IN emp_cursor(d.department_id) LOOP
     dbms_output.put_line('   '||e.employee_id||', '||e.last_name|| ', '|| e.salary);
     END LOOP;
     END LOOP;
END;

(11)使用者輸入一個任意部門的編號,更新這個部門的員工工資
     如果有員工更新,輸出‘更新成果,有XX個員工被更新’
     如果沒有員工更新,輸出‘這個部門不存在,沒有任何員工被更新’

DECLARE
      v_deptid NUMBER :=&input;
BEGIN
  UPDATE employees
  SET salary = salary +1
  WHERE department_id = v_deptid;
 
  IF SQL%FOUND THEN
    dbms_output.put_line('更新成!有'||SQL%ROWCOUNT ||'個員工被更新');
    ELSE
    dbms_output.put_line('這個部門不存在,沒有任何員工被更新');
    END IF;
    COMMIT;
END;


(12)通過遊標去更新員工的工資,如果低於5000塊,則把工資改為5000

DECLARE
    CURSOR emp_cursor IS
    SELECT * FROM new_emp FOR UPDATE;
BEGIN
  FOR e IN emp_cursor LOOP
    IF e.salary<8300 THEN
      UPDATE new_emp SET salary =8300 WHERE CURRENT OF emp_cursor;
    END IF;
  
  END LOOP;
  
END;


(13)通過遊標刪除工資=5000的員工

DECLARE
    CURSOR emp_cursor IS
    SELECT * FROM new_emp FOR UPDATE;
BEGIN
  FOR e IN emp_cursor LOOP
    IF e.salary = 6000 THEN
      DELETE FROM new_emp WHERE CURRENT OF emp_cursor;
      END IF;
  END LOOP;


END;



(14)使用者輸入一個字母,輸入E,輸出所有員工姓名,如果輸出D,輸出所有部門名稱(遊標變數(動態遊標))

DECLARE
      v_cmd CHAR(1):='&input';
     v_name VARCHAR2(50);
     //宣告自定義的遊標變數型別
     TYPE c_type IS REF CURSOR;
    //宣告變數
    c c_type;
    c SYS_REFCURSOR;--相當於 c_type is ref cursor
BEGIN
  IF v_cmd = 'E' THEN
     dbms_output.put_line('員工姓名');
      OPEN c FOR
      SELECT last_name FROM employees;
  ELSIF v_cmd = 'D' THEN
     dbms_output.put_line('部門名稱');
     O PEN c FOR
      SELECT department_name FROM departments;
  ELSE
    dbms_output.put_line('請正確輸入');
    RETURN;
    END IF;
  LOOP
    FETCH  c
     INTO  v_name;
     EXIT  WHEN c%NOTFOUND;
     dbms_output.put_line(v_name);
   END ;