Oracle——遊標

簡介

PL/SQL 是用遊標來管理 SQL 的 SELECT 語句的 。遊標是爲了處理這些語句而分配的一大塊內存。 它提供了對一個結果集進行逐行處理的能力 , 可看作是一種特殊的指針 . 它與某個查詢結果集相關聯 , 可以指向結果集的任意位置 , 以便對指定位置的數據進行處理 。使用它可以在查詢數據的同時對數據進行處理。

遊標類型

隱式遊標

1、使用DML語句(增刪改)和單行查詢語句(賦值)時自動創建隱式遊標

2、隱式遊標自動聲明、打開和關閉,其名爲 SQL

3、通過檢查隱式遊標的屬性可以獲得最近執行的DML 語句的信息

4、隱式遊標的屬性:

(1)、%FOUND:SQL 語句影響了一行或多行時爲 TRUE。只有在 DML 語句影響一行或多行時,才返回 True。

BEGIN
	UPDATE t_student SET sname = '張三丰'
	WHERE sid= ‘10001';

	IF  SQL%FOUND  THEN
		DBMS_OUTPUT.PUT_LINE('表已更新');
	END IF;
     END;

(2)、%NOTFOUND : SQL 語句沒有影響任何行時爲TRUE。如果 DML 語句不影響任何行,則返回 True。

 BEGIN
             UPDATE emp SET deptno=20 WHERE empno=7839;  
            IF SQL%NOTFOUND  THEN
                             DBMS_OUTPUT.PUT_LINE('編號未找到。');
 	ELSE
		DBMS_OUTPUT.PUT_LINE(‘數據已更新');
	END IF;
     END;

(3)、%ROWCOUNT : SQL 語句影響的行數,沒有影響任何行,返回0,在執行任何DML語句前,值爲NULL。

如果沒有與SELECT INTO語句中的條件匹配的行,將引發NO_DATA_FOUND異常。

DECLARE 
	v_no  emp.empno%type;
	v_name emp.ename%type;
 BEGIN
	v_no:= &職員編號;
	SELECT ename INTO  v_name 
	FROM  emp  WHERE  empno=v_no;
     IF SQL%ROWCOUNT>0 THEN
	  DBMS_OUTPUT.PUT_LINE('職員的姓名是 '||v_name);
     END IF;
	EXCEPTION
	   WHEN NO_DATA_FOUND THEN
	     DBMS_OUTPUT.PUT_LINE('職員未找到');
 END;

(4)、%ISOPEN  : 遊標是否打開,隱式遊標始終爲FALSE(隱式遊標執行時打開,結束時立即關閉)

顯示遊標

1、顯式遊標是由PL/SQL程序員定義和命名的遊標

2、顯式遊標用於多行查詢

3、顯式遊標需要在PL/SQL塊的聲明部分聲明,在執行部分或異常處理部分打開,取完數據後將其關閉

聲明遊標

CURSOR  cursor_name  IS  select_statement;

打開遊標(將數據存儲到遊標)

OPEN  cursor_name;

根據遊標提取數據

FETCH  cursor_name  INTO variable[,variable,……]

關閉遊標

CLOSE  cursor_name;

使用遊標循環打印所有學生姓名

Declare
  v_name t_student.sname%type;
  Cursor cur_stu Is select  sname  from t_student; --聲明遊標
begin
  Open cur_stu; --打開遊標
  Loop
    Fetch cur_stu Into  v_name;  --提取遊標指向數據給變量
    Exit When cur_stu%NotFound;
    dbms_output.put_line('學生姓名:'||v_name); 
  End Loop;
  Close cur_stu;  --關閉遊標
end;

使用遊標循環打印所有員工編號,員工姓名及工資

declare
  CURSOR c_emp IS
    SELECT empno,ename,sal FROM emp ORDER BY sal;
  v_empno emp.empno%TYPE;
  v_ename emp.ename%TYPE;
  v_sal emp.sal%TYPE;
begin
  Open c_emp;
  Loop
    Fetch c_emp Into  v_empno,v_ename,v_sal;
    Exit When c_emp%NotFound;
    dbms_output.put_line(v_empno||’  ’||v_ename||’  ’||v_sal); 
  End Loop;
  Close c_emp;
end;

使用遊標循環打印所有員工編號,員工姓名及工資

declare
  CURSOR c_emp IS
    SELECT empno,ename,sal FROM emp ORDER BY sal;
  v_empno emp.empno%TYPE;
  v_ename emp.ename%TYPE;
  v_sal emp.sal%TYPE;
begin
  Open c_emp;
  Loop
    Fetch c_emp Into  v_empno,v_ename,v_sal;
    Exit When c_emp%NotFound;
    dbms_output.put_line(v_empno||’  ’||v_ename||’  ’||v_sal); 
  End Loop;
  Close c_emp;
end;

使用遊標行循環打印員工編號,姓名,工資

declare
  CURSOR c_emp IS
    SELECT empno,ename,sal FROM emp ORDER BY sal; 
    r_emp c_emp%ROWTYPE;--遊標行
begin
  Open c_emp;
  Loop
    Fetch c_emp Into r_emp;
    Exit When c_emp%NotFound;
dbms_output.put_line(r_emp.empno||’  ’||r_emp.ename||’  ’||r_emp.sal);
  End Loop;
  Close c_emp;
end;

使用遊標行循環打印員工編號,姓名,工資

declare
  CURSOR c_emp IS
    SELECT empno,ename,sal FROM emp ORDER BY sal; 
    r_emp c_emp%ROWTYPE;--遊標行
begin
  Open c_emp;
  Loop
    Fetch c_emp Into r_emp;
    Exit When c_emp%NotFound;
dbms_output.put_line(r_emp.empno||’  ’||r_emp.ename||’  ’||r_emp.sal);
  End Loop;
  Close c_emp;
end;

帶參數的顯示遊標

聲明顯式遊標時可以帶參數以提高靈活性

declare
   v_deptno emp.deptno%type; --部門編號變量
   cursor c_emp(dno number) is
        select empno,ename,sal from emp where deptno=dno; 
    r_emp c_emp%rowtype; --遊標行
begin
  v_deptno:='&部門編號'; --輸入參數值
  Open c_emp(v_deptno);--傳遞參數
  Loop
    Fetch c_emp Into r_emp;
    Exit When c_emp%NotFound;
dbms_output.put_line(r_emp.empno||'  '||r_emp.ename||'  '||r_emp.sal);
  End Loop;
  Close c_emp;
end;

循環遊標

1、循環遊標用於簡化遊標處理代碼

2、當用戶需要從遊標中提取多行記錄時使用

3、循環遊標的語法如下:

FOR  record_name  IN  (corsor_name[(parameter[,parameter])...]) 
| (query_difinition)
LOOP
 statements
END LOOP;
DECLARE
	CURSOR c_emp  IS
       SELECT empno,ename,sal FROM  emp ORDER BY sal;
BEGIN
  FOR r_emp IN  c_emp  
Loop  -- r_emp代表遊標行
    dbms_output.put_line(r_emp.empno||’’||r_emp.ename||’’||r_emp.sal);
  End Loop;	
END;

用於FOR循環的遊標聲明按照正常聲明方式聲明;不需要顯式的打開,取數據,測試數據存在,關閉等;帶參數時,in 遊標名(參數)。

允許使用遊標刪除或更新活動集中的行,聲明遊標時必須使用 SELECT … FOR UPDATE語句

CURSOR <cursor_name> IS
	  select_statement FOR UPDATE [OF columns];

更新數據格式

UPDATE <table_name>
	SET column_name = column_value
	WHERE CURRENT OF <cursor_name>

刪除數據格式

DELETE FROM <table_name>
WHERE CURRENT OF <cursor_name>
DECLARE 
   CURSOR c_emp IS
     SELECT empno,ename,sal FROM emp ORDER BY sal DESC FOR UPDATE;
   v_increase NUMBER:=0;    --增加的工資數
   v_new_sal NUMBER;    --新工資
BEGIN
   FOR r_emp IN c_emp LOOP
     v_new_sal:=r_emp.sal+v_increase;
     UPDATE emp SET sal=v_new_sal WHERE CURRENT OF c_emp;
     DBMS_OUTPUT.PUT_LINE(r_emp.empno||' '||r_emp.ename||
     '  old salary ='||r_emp.sal||'  new salary='||v_new_sal);
     v_increase:=v_increase+100;
   END LOOP;
END;

REF 遊標

REF 遊標和遊標變量用於處理運行時動態執行的 SQL 查詢,創建遊標變量需要兩個步驟:

1、聲明 REF 遊標類型

TYPE <ref_cursor_name> IS REF CURSOR
	[RETURN <return_type>];

2、聲明 REF 遊標類型的變量

ref_variable  ref_cursor_name;

打開遊標變量的語法

OPEN ref_variable FOR   select_statement;
declare 
  type refcur is ref cursor;
  ref_cur refcur;
  r_emp   emp%rowtype;
  r_dept   dept%rowtype;
  selection varchar2(1):=upper(substr('&input',1,1));
begin  
  if selection='E'  then
     open ref_cur for select * from emp;
     dbms_output.put_line('=========員工信息=========');
     loop
         fetch ref_cur into r_emp;
         exit when ref_cur%notfound;
         dbms_output.put_line(r_emp.empno||'   '||r_emp.ename||'   '||r_emp.sal);        
     end loop;
 elsif  selection='D' then
   
     open ref_cur for select * from dept;
     dbms_output.put_line('=========部門信息=========');
     loop  
     fetch ref_cur into r_dept ;
     exit when ref_cur%notfound;
     dbms_output.put_line(r_dept.deptno||'  '||r_dept.dname||'   ');
     end loop;
  else
     dbms_output.put_line('請輸入員工信息(E)或 部門信息(D)');
     return;     
  end if;
  close ref_cur;
end;

遊標變量的優點和限制

1、遊標變量的功能強大,可以簡化數據處理。

2、遊標變量的優點有:

(1)、可從不同的 SELECT 語句中提取結果集

(2)、可以作爲過程的參數進行傳遞

(3)、可以引用遊標的所有屬性

(4)、可以進行賦值運算

3、使用遊標變量的限制:

(1)、不能在程序包中聲明遊標變量

(2)、FOR UPDATE子句不能與遊標變量一起使用

(3)、不能使用比較運算符

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章