現在的位置: 首頁 > 資料庫 > 正文

Oracle游標使用大全

2018年08月12日 資料庫 ⁄ 共 4258字 ⁄ 字型大小 評論關閉

 

從游標提取數據
  從游標得到一行數據使用FETCH命令。每一次提取數據後,游標都指向結果集的下一行。語法如下:
  FETCH cursor_name INTO variable[,variable,...]
  對於SELECT定義的游標的每一列,FETCH變數列表都應該有一個變數與之相對應,變數的類型也要相同。

 

例:
  SET SERVERIUTPUT ON
  DECLARE
  v_ename EMP.ENAME%TYPE;
  v_salary EMP.SALARY%TYPE;
  CURSOR c_emp IS SELECT ename,salary FROM emp;
  BEGIN
    OPEN c_emp;
      FETCH c_emp INTO v_ename,v_salary;
        DBMS_OUTPUT.PUT_LINE('Salary of Employee'|| v_ename ||'is'|| v_salary);
      FETCH c_emp INTO v_ename,v_salary;
        DBMS_OUTPUT.PUT_LINE('Salary of Employee'|| v_ename ||'is'|| v_salary);
      FETCH c_emp INTO v_ename,v_salary;
        DBMS_OUTPUT.PUT_LINE('Salary of Employee'|| v_ename ||'is'|| v_salary);
    CLOSE c_emp;
  END
   
  這段代碼無疑是非常麻煩的,如果有多行返回結果,可以使用循環並用游標屬性為結束循環的條件,以這種方式提取數據,程序的可讀性和簡潔性都大為提高,下面我們使用循環重新寫上面的程序:
SET SERVERIUTPUT ON
DECLARE
v_ename EMP.ENAME%TYPE;
v_salary EMP.SALARY%TYPE;
CURSOR c_emp IS SELECT ename,salary FROM emp;
BEGIN
OPEN c_emp;
  LOOP
    FETCH c_emp INTO v_ename,v_salary;
    EXIT WHEN c_emp%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE('Salary of Employee'|| v_ename ||'is'|| v_salary);
END

記錄變數
  定義一個記錄變數使用TYPE命令和%ROWTYPE,關於%ROWsTYPE的更多信息請參閱相關資料。
  記錄變數用於從游標中提取數據行,當游標選擇很多列的時候,那麼使用記錄比為每列聲明一個變數要方便得多。
  當在表上使用%ROWTYPE並將從游標中取出的值放入記錄中時,如果要選擇表中所有列,那麼在SELECT子句中使用*比將所有列名列出來要得多。

 

例:
SET SERVERIUTPUT ON
DECLARE
R_emp EMP%ROWTYPE;
CURSOR c_emp IS SELECT * FROM emp;
BEGIN
OPEN c_emp;
  LOOP
  FETCH c_emp INTO r_emp;
  EXIT WHEN c_emp%NOTFOUND;
  DBMS_OUT.PUT.PUT_LINE('Salary of Employee'||r_emp.ename||'is'|| r_emp.salary);
  END LOOP;
CLOSE c_emp;
END;

 

%ROWTYPE也可以用游標名來定義,這樣的話就必須要首先聲明游標:

 

SET SERVERIUTPUT ON
DECLARE
CURSOR c_emp IS SELECT ename,salary FROM emp;
R_emp c_emp%ROWTYPE;
BEGIN
OPEN c_emp;
LOOP
  FETCH c_emp INTO r_emp;
  EXIT WHEN c_emp%NOTFOUND;
  DBMS_OUT.PUT.PUT_LINE('Salary of Employee'||r_emp.ename||'is'|| r_emp.salary);
END LOOP;
CLOSE c_emp;
END;

帶參數的游標
  與存儲過程和函數相似,可以將參數傳遞給游標並在查詢中使用。這對於處理在某種條件下打開游標的情況非常有用。它的語法如下:

 

CURSOR cursor_name[(parameter[,parameter],...)] IS select_statement;

 

定義參數的語法如下:
  Parameter_name [IN] data_type[{:=|DEFAULT} value]

 

  與存儲過程不同的是,游標只能接受傳遞的值,而不能返回值。參數只定義數據類型,沒有大小。
  另外可以給參數設定一個預設值,當沒有參數值傳遞給游標時,就使用預設值。游標中定義的參數只是一個佔位符,在別處引用該參數不一定可靠。

 

在打開游標時給參數賦值,語法如下:

 

OPEN cursor_name[value[,value]....];
參數值可以是文字或變數。

 

例:
DECALRE
CURSOR c_dept IS SELECT * FROM dept ORDER BY deptno;
CURSOR c_emp (p_dept VARACHAR2) IS
SELECT ename,salary
FROM emp
WHERE deptno=p_dept
ORDER BY ename
r_dept DEPT%ROWTYPE;
v_ename EMP.ENAME%TYPE;
v_salary EMP.SALARY%TYPE;
v_tot_salary EMP.SALARY%TYPE;
BEGIN
OPEN c_dept;
  LOOP
    FETCH c_dept INTO r_dept;
    EXIT WHEN c_dept%NOTFOUND;
    DBMS_OUTPUT.PUT_LINE('Department:'|| r_dept.deptno||'-'||r_dept.dname);
    v_tot_salary:=0;
    OPEN c_emp(r_dept.deptno);
        LOOP
          FETCH c_emp INTO v_ename,v_salary;
          EXIT WHEN c_emp%NOTFOUND;
          DBMS_OUTPUT.PUT_LINE('Name:'|| v_ename||' salary:'||v_salary);
          v_tot_salary:=v_tot_salary+v_salary;
        END LOOP;
    CLOSE c_emp;
    DBMS_OUTPUT.PUT_LINE('Toltal Salary for dept:'|| v_tot_salary);
  END LOOP;
CLOSE c_dept;
END;

游標FOR循環
在大多數時候我們在設計程序的時候都遵循下面的步驟:
1、打開游標
2、開始循環
3、從游標中取值
那一行被返回
5、處理
6、關閉循環
7、關閉游標
  可以簡單的把這一類代碼稱為游標用於循環。但還有一種循環與這種類型不相同,這就是FOR循環,用於FOR循環的游標按照正常的聲明方式聲明,它的優點在於不需要顯式的打開、關閉、取數據,測試數據的存在、定義存放數據的變數等等。游標FOR循環的語法如下:

 

FOR record_name IN
(corsor_name[(parameter[,parameter]...)]
| (query_difinition)
LOOP
statements
END LOOP;

 

下面我們用for循環重寫上面的例子:
DECALRE
CURSOR c_dept IS SELECT deptno,dname FROM dept ORDER BY deptno;
CURSOR c_emp (p_dept VARACHAR2) IS
SELECT ename,salary
FROM emp
WHERE deptno=p_dept
ORDER BY ename
v_tot_salary EMP.SALARY%TYPE;
BEGIN
  FOR r_dept IN c_dept LOOP
  DBMS_OUTPUT.PUT_LINE('Department:'|| r_dept.deptno||'-'||r_dept.dname);
  v_tot_salary:=0;
  FOR r_emp IN c_emp(r_dept.deptno) LOOP
  DBMS_OUTPUT.PUT_LINE('Name:' || v_ename || 'salary:' || v_salary);  
  v_tot_salary:=v_tot_salary+v_salary;
  END LOOP;
  DBMS_OUTPUT.PUT_LINE('Toltal Salary for dept:'|| v_tot_salary);
END LOOP;
END;

在游標FOR循環中使用查詢
  在游標FOR循環中可以定義查詢,由於沒有顯式聲明所以游標沒有名字,記錄名通過游標查詢來定義。
DECALRE
v_tot_salary EMP.SALARY%TYPE;
BEGIN
FOR r_dept IN (SELECT deptno,dname FROM dept ORDER BY deptno) LOOP
  DBMS_OUTPUT.PUT_LINE('Department:'|| r_dept.deptno||'-'||r_dept.dname);
  v_tot_salary:=0;
  FOR r_emp IN (SELECT ename,salary
           FROM emp
           WHERE deptno=p_dept
           ORDER BY ename) LOOP
    DBMS_OUTPUT.PUT_LINE('Name:'|| v_ename||' salary:'||v_salary);
    v_tot_salary:=v_tot_salary+v_salary;
  END LOOP;
DBMS_OUTPUT.PUT_LINE('Toltal Salary for dept:'|| v_tot_salary);
END LOOP;
END;

 

游標中的子查詢
  語法如下:
 
CURSOR C1 IS SELECT * FROM emp
WHERE deptno NOT IN (SELECT deptno
  FROM dept
  WHERE dname!='ACCOUNTING');
可以看出與SQL中的子查詢沒有什麼區別。

 

 

抱歉!評論已關閉.