好湿?好紧?好多水好爽自慰,久久久噜久噜久久综合,成人做爰A片免费看黄冈,机机对机机30分钟无遮挡

主頁(yè) > 知識(shí)庫(kù) > Oracle中游標(biāo)Cursor基本用法詳解

Oracle中游標(biāo)Cursor基本用法詳解

熱門(mén)標(biāo)簽:安陽(yáng)外呼系統(tǒng)免費(fèi) 海南400電話(huà)哪里辦理 呼倫貝爾智能手機(jī)地圖標(biāo)注 400電話(huà)是不是免費(fèi)申請(qǐng) 濟(jì)南地圖標(biāo)注公司 貴陽(yáng)電話(huà)外呼系統(tǒng)哪家好 圖像地圖標(biāo)注 南寧人工智能電銷(xiāo)機(jī)器人費(fèi)用 分布式呼叫中心

查詢(xún)

  SELECT語(yǔ)句用于從數(shù)據(jù)庫(kù)中查詢(xún)數(shù)據(jù),當(dāng)在PL/SQL中使用SELECT語(yǔ)句時(shí),要與INTO子句一起使用,查詢(xún)的
返回值被賦予INTO子句中的變量,變量的聲明是在DELCARE中。SELECT INTO語(yǔ)法如下:

  SELECT [DISTICT|ALL]{*|column[,column,...]}
  INTO (variable[,variable,...] |record)
  FROM {table|(sub-query)}[alias]
  WHERE............

  PL/SQL中SELECT語(yǔ)句只返回一行數(shù)據(jù)。如果超過(guò)一行數(shù)據(jù),那么就要使用顯式游標(biāo)(對(duì)游標(biāo)的討論我們將
在后面進(jìn)行),INTO子句中要有與SELECT子句中相同列數(shù)量的變量。INTO子句中也可以是記錄變量。

%TYPE屬性

  在PL/SQL中可以將變量和常量聲明為內(nèi)建或用戶(hù)定義的數(shù)據(jù)類(lèi)型,以引用一個(gè)列名,同時(shí)繼承他的數(shù)據(jù)類(lèi)
型和大小。這種動(dòng)態(tài)賦值方法是非常有用的,比如變量引用的列的數(shù)據(jù)類(lèi)型和大小改變了,如果使用了%TYPE,
那么用戶(hù)就不必修改代碼,否則就必須修改代碼。

例:

  v_empno SCOTT.EMP.EMPNO%TYPE;
  v_salary EMP.SALARY%TYPE;

  不但列名可以使用%TYPE,而且變量、游標(biāo)、記錄,或聲明的常量都可以使用%TYPE。這對(duì)于定義相同數(shù)據(jù)類(lèi)
型的變量非常有用。

  DELCARE
   V_A NUMBER(5):=10;
  V_B V_A%TYPE:=15;
  V_C V_A%TYPE;
  BEGIN
  DBMS_OUTPUT.PUT_LINE
  ('V_A='||V_A||'V_B='||V_B||'V_C='||V_C);
  END
  SQL>/
  V_A=10 V_B=15 V_C=
  PL/SQL procedure successfully completed.
  SQL>

其他DML語(yǔ)句

其它操作數(shù)據(jù)的DML語(yǔ)句是:INSERT、UPDATE、DELETE和LOCK TABLE,這些語(yǔ)句在PL/SQL中的語(yǔ)法與在SQL中
的語(yǔ)法相同。我們?cè)谇懊嬉呀?jīng)討

論過(guò)DML語(yǔ)句的使用這里就不再重復(fù)了。在DML語(yǔ)句中可以使用任何在DECLARE部分聲明的變量,如果是嵌套
塊,那么要注意變量的作用范圍。

例:

  CREATE OR REPLACE PROCEDURE FIRE_EMPLOYEE (pempno in number)
  AS
  v_ename EMP.ENAME%TYPE;
  BEGIN
  SELECT ename INTO v_ename
  FROM emp
  WHERE empno=p_empno;
  INSERT INTO FORMER_EMP(EMPNO,ENAME)
  VALUES (p_empno,v_ename);
  DELETE FROM emp
  WHERE empno=p_empno;
  UPDATE former_emp
  SET date_deleted=SYSDATE
  WHERE empno=p_empno;
  EXCEPTION
  WHEN NO_DATA_FOUND THEN
  DBMS_OUTPUT.PUT_LINE('Employee Number Not Found!');
  END

  DML語(yǔ)句的結(jié)果

當(dāng)執(zhí)行一條DML語(yǔ)句后,DML語(yǔ)句的結(jié)果保存在四個(gè)游標(biāo)屬性中,這些屬性用于控制程序流程或者了解程序
的狀態(tài)。當(dāng)運(yùn)行DML語(yǔ)句時(shí),PL/SQL打開(kāi)一個(gè)內(nèi)建游標(biāo)并處理結(jié)果,游標(biāo)是維護(hù)查詢(xún)結(jié)果的內(nèi)存中的一個(gè)區(qū)域,
游標(biāo)在運(yùn)行DML語(yǔ)句時(shí)打開(kāi),完成后關(guān)閉。隱式游標(biāo)只使用SQL%FOUND,

SQL%NOTFOUND,SQL%ROWCOUNT三個(gè)屬性.SQL%FOUND,SQL%NOTFOUND是布爾值,SQL%ROWCOUNT是整數(shù)值。

SQL%FOUND和SQL%NOTFOUND

在執(zhí)行任何DML語(yǔ)句前SQL%FOUND和SQL%NOTFOUND的值都是NULL,在執(zhí)行DML語(yǔ)句后,SQL%FOUND的屬性值將是:

  . TRUE :INSERT
  . TRUE :DELETE和UPDATE,至少有一行被DELETE或UPDATE.
  . TRUE :SELECT INTO至少返回一行

當(dāng)SQL%FOUND為T(mén)RUE時(shí),SQL%NOTFOUND為FALSE。

SQL%ROWCOUNT

在執(zhí)行任何DML語(yǔ)句之前,SQL%ROWCOUNT的值都是NULL,對(duì)于SELECT INTO語(yǔ)句,如果執(zhí)行成功
,SQL%ROWCOUNT的值為1,如果沒(méi)有成功,SQL%ROWCOUNT的值為0,同時(shí)產(chǎn)生一個(gè)異常NO_DATA_FOUND.

SQL%ISOPEN

SQL%ISOPEN是一個(gè)布爾值,如果游標(biāo)打開(kāi),則為T(mén)RUE, 如果游標(biāo)關(guān)閉,則為FALSE.對(duì)于隱式游標(biāo)而言SQL%
ISOPEN總是FALSE,這是因?yàn)殡[式游

標(biāo)在DML語(yǔ)句執(zhí)行時(shí)打開(kāi),結(jié)束時(shí)就立即關(guān)閉。

事務(wù)控制語(yǔ)句

事務(wù)是一個(gè)工作的邏輯單元可以包括一個(gè)或多個(gè)DML語(yǔ)句,事物控制幫助用戶(hù)保證數(shù)據(jù)的一致性。如果事務(wù)控制邏輯單元中的任何一個(gè)DML
語(yǔ)句失敗,那么整個(gè)事務(wù)都將回滾,在PL/SQL中用戶(hù)可以明確地使用COMMIT、ROLLBACK、SAVEPOINT以及
SET TRANSACTION語(yǔ)句。

COMMIT語(yǔ)句終止事務(wù),永久保存數(shù)據(jù)庫(kù)的變化,同時(shí)釋放所有LOCK,ROLLBACK終止現(xiàn)行事務(wù)釋放所有LOCK,
但不保存數(shù)據(jù)庫(kù)的任何變化,SAVEPOI

NT用于設(shè)置中間點(diǎn),當(dāng)事務(wù)調(diào)用過(guò)多的數(shù)據(jù)庫(kù)操作時(shí),中間點(diǎn)是非常有用的,SET TRANSACTION用于設(shè)置事
務(wù)屬性,比如read-write和隔離級(jí)等。

顯式游標(biāo)

查詢(xún)返回結(jié)果超過(guò)一行時(shí),就需要一個(gè)顯式游標(biāo),此時(shí)用戶(hù)不能使用select into語(yǔ)句。PL/SQL管理隱式
游標(biāo),當(dāng)查詢(xún)開(kāi)始時(shí)隱式游標(biāo)打開(kāi),查詢(xún)結(jié)束時(shí)隱式游標(biāo)自動(dòng)關(guān)閉。顯式游標(biāo)在PL/SQL塊的聲明部分聲明,在執(zhí)行部分或異常處理部分打開(kāi),取數(shù)據(jù),關(guān)閉。

使用游標(biāo)

這里要做一個(gè)聲明,我們所說(shuō)的游標(biāo)通常是指顯式游標(biāo),因此從現(xiàn)在起沒(méi)有特別指明的情況,我們所說(shuō)的
游標(biāo)都是指顯式游標(biāo)。要在程序中使用游標(biāo),必須首先聲明游標(biāo)。

聲明游標(biāo)

語(yǔ)法:

CURSOR cursor_name IS select_statement;

在PL/SQL中游標(biāo)名是一個(gè)未聲明變量,不能給游標(biāo)名賦值或用于表達(dá)式中。

例:

  DELCARE
  CURSOR C_EMP IS SELECT empno,ename,salary
  FROM emp
  WHERE salary>2000
  ORDER BY ename;
  ........
  BEGIN

  在游標(biāo)定義中SELECT語(yǔ)句中不一定非要表可以是視圖,也可以從多個(gè)表或視圖中選擇的列,甚至可以使用*
來(lái)選擇所有的列 。

打開(kāi)游標(biāo)

使用游標(biāo)中的值之前應(yīng)該首先打開(kāi)游標(biāo),打開(kāi)游標(biāo)初始化查詢(xún)處理。打開(kāi)游標(biāo)的語(yǔ)法是:

  OPEN cursor_name

 cursor_name是在聲明部分定義的游標(biāo)名。

例:

OPEN C_EMP;

  關(guān)閉游標(biāo)

語(yǔ)法:

 CLOSE cursor_name

例:

CLOSE C_EMP;

從游標(biāo)提取數(shù)據(jù)

從游標(biāo)得到一行數(shù)據(jù)使用FETCH命令。每一次提取數(shù)據(jù)后,游標(biāo)都指向結(jié)果集的下一行。語(yǔ)法如下:

FETCH cursor_name INTO variable[,variable,...]

對(duì)于SELECT定義的游標(biāo)的每一列,F(xiàn)ETCH變量列表都應(yīng)該有一個(gè)變量與之相對(duì)應(yīng),變量的類(lèi)型也要相同。

例:

  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

這段代碼無(wú)疑是非常麻煩的,如果有多行返回結(jié)果,可以使用循環(huán)并用游標(biāo)屬性為結(jié)束循環(huán)的條件,以這
種方式提取數(shù)據(jù),程序的可讀性和簡(jiǎn)潔性都大為提高,下面我們使用循環(huán)重新寫(xiě)上面的程序:

  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

  記錄變量

定義一個(gè)記錄變量使用TYPE命令和%ROWTYPE,關(guān)于%ROWsTYPE的更多信息請(qǐng)參閱相關(guān)資料。

記錄變量用于從游標(biāo)中提取數(shù)據(jù)行,當(dāng)游標(biāo)選擇很多列的時(shí)候,那么使用記錄比為每列聲明一個(gè)變量要方
便得多。

當(dāng)在表上使用%ROWTYPE并將從游標(biāo)中取出的值放入記錄中時(shí),如果要選擇表中所有列,那么在SELECT子句
中使用*比將所有列名列出來(lái)要安全得多。

例:

  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也可以用游標(biāo)名來(lái)定義,這樣的話(huà)就必須要首先聲明游標(biāo):

  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;

帶參數(shù)的游標(biāo)

與存儲(chǔ)過(guò)程和函數(shù)相似,可以將參數(shù)傳遞給游標(biāo)并在查詢(xún)中使用。這對(duì)于處理在某種條件下打開(kāi)游標(biāo)的情
況非常有用。它的語(yǔ)法如下:

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

定義參數(shù)的語(yǔ)法如下:

Parameter_name [IN] data_type[{:=|DEFAULT} value]

與存儲(chǔ)過(guò)程不同的是,游標(biāo)只能接受傳遞的值,而不能返回值。參數(shù)只定義數(shù)據(jù)類(lèi)型,沒(méi)有大小。

另外可以給參數(shù)設(shè)定一個(gè)缺省值,當(dāng)沒(méi)有參數(shù)值傳遞給游標(biāo)時(shí),就使用缺省值。游標(biāo)中定義的參數(shù)只是一個(gè)占位符,在別處引用該參數(shù)不一定可靠。

在打開(kāi)游標(biāo)時(shí)給參數(shù)賦值,語(yǔ)法如下:

OPEN cursor_name[value[,value]....];

參數(shù)值可以是文字或變量。

例:

  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;

  游標(biāo)FOR循環(huán)

在大多數(shù)時(shí)候我們?cè)谠O(shè)計(jì)程序的時(shí)候都遵循下面的步驟:

1、打開(kāi)游標(biāo)
2、開(kāi)始循環(huán)
3、從游標(biāo)中取值
4、檢查那一行被返回
5、處理
6、關(guān)閉循環(huán)
7、關(guān)閉游標(biāo)

可以簡(jiǎn)單的把這一類(lèi)代碼稱(chēng)為游標(biāo)用于循環(huán)。但還有一種循環(huán)與這種類(lèi)型不相同,這就是FOR循環(huán),用于
FOR循環(huán)的游標(biāo)按照正常的聲明方式聲明,它的優(yōu)點(diǎn)在于不需要顯式的打開(kāi)、關(guān)閉、取數(shù)據(jù),測(cè)試數(shù)據(jù)的存在、定義存放數(shù)據(jù)的變量等等。

游標(biāo)FOR循環(huán)的語(yǔ)法如下:

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

  下面我們用for循環(huán)重寫(xiě)上面的例子:

  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;

  在游標(biāo)FOR循環(huán)中使用查詢(xún)

在游標(biāo)FOR循環(huán)中可以定義查詢(xún),由于沒(méi)有顯式聲明所以游標(biāo)沒(méi)有名字,記錄名通過(guò)游標(biāo)查詢(xún)來(lái)定義。

  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;

  游標(biāo)中的子查詢(xún)

  語(yǔ)法如下:

  CURSOR C1 IS SELECT * FROM emp
  WHERE deptno NOT IN (SELECT deptno
  FROM dept
  WHERE dname!='ACCOUNTING');

  可以看出與SQL中的子查詢(xún)沒(méi)有什么區(qū)別。

  游標(biāo)中的更新和刪除

  在PL/SQL中依然可以使用UPDATE和DELETE語(yǔ)句更新或刪除數(shù)據(jù)行。顯式游標(biāo)只有在需要獲得多行數(shù)據(jù)的情
況下使用。PL/SQL提供了僅僅使  用游標(biāo)就可以執(zhí)行刪除或更新記錄的方法。
  UPDATE或DELETE語(yǔ)句中的WHERE CURRENT OF子串專(zhuān)門(mén)處理要執(zhí)行UPDATE或DELETE操作的表中取出的最近的
數(shù)據(jù)。要使用這個(gè)方法,在聲明游標(biāo)  時(shí)必須使用FOR UPDATE子串,當(dāng)對(duì)話(huà)使用FOR UPDATE子串打開(kāi)一個(gè)游標(biāo)時(shí),所有返回集中的數(shù)據(jù)行都將處于行級(jí)(ROW-LEVEL)獨(dú)占式鎖定,其
  他對(duì)象只能查詢(xún)這些數(shù)據(jù)行,不能進(jìn)行UPDATE、DELETE或SELECT...FOR            UPDATE操作。

語(yǔ)法:

  FOR UPDATE [OF [schema.]table.column[,[schema.]table.column]..
  [nowait]

  在多表查詢(xún)中,使用OF子句來(lái)鎖定特定的表,如果忽略了OF子句,那么所有表中選擇的數(shù)據(jù)行都將被鎖定。
如果這些數(shù)據(jù)行已經(jīng)被其他會(huì)話(huà)鎖定,那么正常情況下ORACLE將等待,直到數(shù)據(jù)行解鎖。

  在UPDATE和DELETE中使用WHERE CURRENT OF子串的語(yǔ)法如下:

  WHERE{CURRENT OF cursor_name|search_condition}

  例:

  DELCARE
  CURSOR c1 IS SELECT empno,salary
  FROM emp
  WHERE comm IS NULL
  FOR UPDATE OF comm;
  v_comm NUMBER(10,2);
  BEGIN
  FOR r1 IN c1 LOOP
  IF r1.salary500 THEN
  v_comm:=r1.salary*0.25;
  ELSEIF r1.salary1000 THEN
  v_comm:=r1.salary*0.20;
  ELSEIF r1.salary3000 THEN
  v_comm:=r1.salary*0.15;
  ELSE
  v_comm:=r1.salary*0.12;
  END IF;
  UPDATE emp;
  SET comm=v_comm
  WHERE CURRENT OF c1l;
  END LOOP;
  END
 -聲明游標(biāo)
--宗地表的調(diào)查日期LANDINFO_RESEARCHDATE
--復(fù)制到流程表的權(quán)屬調(diào)查時(shí)間FLOW_REASEARCHTIME
DECLARE 
cursor cur_sel_all is select LANDINFO_RESEARCHDATE,LANDINFO_LANDNO from t_leoa_landinfo; --定義游標(biāo)
   l_date t_leoa_landinfo.landinfo_researchdate%type; --聲明變量分別保存t_leoa_landinfo的各列
   l_landNo t_leoa_landinfo.landinfo_landno%type; 
begin
open cur_sel_all;
  loop                 --循環(huán)取數(shù),并將游標(biāo)數(shù)據(jù)填充到返回紀(jì)錄集合中
   fetch cur_sel_all into l_date,l_landNo;
   exit when cur_sel_all%NOTFOUND; --循環(huán)退出條件
   if cur_sel_all%FOUND then --獲取數(shù)據(jù) 
    update T_LEOA_BOOKFLOW t2 set FLOW_REASEARCHTIME = l_date where l_landNo = t2.landinfo_landno; 
   end if;
  end loop;
close cur_sel_all;
end;

下面再分享一下另外一則游標(biāo)使用方法的代碼,具體如下:

-- 聲明游標(biāo);CURSOR cursor_name IS select_statement
--For 循環(huán)游標(biāo)
--(1)定義游標(biāo)
--(2)定義游標(biāo)變量
--(3)使用for循環(huán)來(lái)使用這個(gè)游標(biāo)
declare
    --類(lèi)型定義
    cursor c_job
    is
    select empno,ename,job,sal
    from emp
    where job='MANAGER';
    --定義一個(gè)游標(biāo)變量v_cinfo c_emp%ROWTYPE ,該類(lèi)型為游標(biāo)c_emp中的一行數(shù)據(jù)類(lèi)型
    c_row c_job%rowtype;
begin
    for c_row in c_job loop
     dbms_output.put_line(c_row.empno||'-'||c_row.ename||'-'||c_row.job||'-'||c_row.sal);
    end loop;
end;
--Fetch游標(biāo)
--使用的時(shí)候必須要明確的打開(kāi)和關(guān)閉
declare 
    --類(lèi)型定義
    cursor c_job
    is
    select empno,ename,job,sal
    from emp
    where job='MANAGER';
    --定義一個(gè)游標(biāo)變量
    c_row c_job%rowtype;
begin
    open c_job;
     loop
      --提取一行數(shù)據(jù)到c_row
      fetch c_job into c_row;
      --判讀是否提取到值,沒(méi)取到值就退出
      --取到值c_job%notfound 是false 
      --取不到值c_job%notfound 是true
      exit when c_job%notfound;
      dbms_output.put_line(c_row.empno||'-'||c_row.ename||'-'||c_row.job||'-'||c_row.sal);
     end loop;
    --關(guān)閉游標(biāo)
   close c_job;
end;
--1:任意執(zhí)行一個(gè)update操作,用隱式游標(biāo)sql的屬性%found,%notfound,%rowcount,%isopen觀察update語(yǔ)句的執(zhí)行情況。
    begin
     update emp set ENAME='ALEARK' WHERE EMPNO=7469;
     if sql%isopen then
      dbms_output.put_line('Openging');
      else
       dbms_output.put_line('closing');
       end if;
     if sql%found then
      dbms_output.put_line('游標(biāo)指向了有效行');--判斷游標(biāo)是否指向有效行
      else
       dbms_output.put_line('Sorry');
       end if;
       if sql%notfound then
        dbms_output.put_line('Also Sorry');
        else
         dbms_output.put_line('Haha');
         end if;
          dbms_output.put_line(sql%rowcount);
          exception 
           when no_data_found then
            dbms_output.put_line('Sorry No data');
            when too_many_rows then
             dbms_output.put_line('Too Many rows');
             end;
declare
    empNumber emp.EMPNO%TYPE;
    empName emp.ENAME%TYPE;
    begin
     if sql%isopen then
      dbms_output.put_line('Cursor is opinging');
      else
       dbms_output.put_line('Cursor is Close');
       end if;
       if sql%notfound then
        dbms_output.put_line('No Value');
        else
         dbms_output.put_line(empNumber);
         end if;
         dbms_output.put_line(sql%rowcount);
         dbms_output.put_line('-------------');
         select EMPNO,ENAME into empNumber,empName from emp where EMPNO=7499;
         dbms_output.put_line(sql%rowcount);
        if sql%isopen then
        dbms_output.put_line('Cursor is opinging');
        else
        dbms_output.put_line('Cursor is Closing');
        end if;
         if sql%notfound then
         dbms_output.put_line('No Value');
         else
         dbms_output.put_line(empNumber);
         end if;
         exception 
          when no_data_found then
           dbms_output.put_line('No Value');
           when too_many_rows then
            dbms_output.put_line('too many rows');
            end;
--2,使用游標(biāo)和loop循環(huán)來(lái)顯示所有部門(mén)的名稱(chēng)
--游標(biāo)聲明
declare 
    cursor csr_dept
    is
    --select語(yǔ)句
    select DNAME
    from Depth;
    --指定行指針,這句話(huà)應(yīng)該是指定和csr_dept行類(lèi)型相同的變量
    row_dept csr_dept%rowtype;
begin
    --for循環(huán)
    for row_dept in csr_dept loop
      dbms_output.put_line('部門(mén)名稱(chēng):'||row_dept.DNAME);
    end loop;
end;
--3,使用游標(biāo)和while循環(huán)來(lái)顯示所有部門(mén)的的地理位置(用%found屬性)
declare
    --游標(biāo)聲明
    cursor csr_TestWhile
    is
    --select語(yǔ)句
    select LOC
    from Depth;
    --指定行指針
    row_loc csr_TestWhile%rowtype;
begin
 --打開(kāi)游標(biāo)
    open csr_TestWhile;
    --給第一行喂數(shù)據(jù)
    fetch csr_TestWhile into row_loc;
    --測(cè)試是否有數(shù)據(jù),并執(zhí)行循環(huán)
     while csr_TestWhile%found loop
      dbms_output.put_line('部門(mén)地點(diǎn):'||row_loc.LOC);
      --給下一行喂數(shù)據(jù)
      fetch csr_TestWhile into row_loc;
     end loop;
    close csr_TestWhile;
end; 
select * from emp
    
--4,接收用戶(hù)輸入的部門(mén)編號(hào),用for循環(huán)和游標(biāo),打印出此部門(mén)的所有雇員的所有信息(使用循環(huán)游標(biāo))
--CURSOR cursor_name[(parameter[,parameter],...)] IS select_statement;
--定義參數(shù)的語(yǔ)法如下:Parameter_name [IN] data_type[{:=|DEFAULT} value] 
declare 
   CURSOR 
   c_dept(p_deptNo number)
   is
   select * from emp where emp.depno=p_deptNo;
   r_emp emp%rowtype;
begin
    for r_emp in c_dept(20) loop
      dbms_output.put_line('員工號(hào):'||r_emp.EMPNO||'員工名:'||r_emp.ENAME||'工資:'||r_emp.SAL);
    end loop;
end;
select * from emp  
--5:向游標(biāo)傳遞一個(gè)工種,顯示此工種的所有雇員的所有信息(使用參數(shù)游標(biāo))
declare 
    cursor
    c_job(p_job nvarchar2)
    is 
    select * from emp where JOB=p_job;
    r_job emp%rowtype;
begin 
    for r_job in c_job('CLERK') loop
      dbms_output.put_line('員工號(hào)'||r_job.EMPNO||' '||'員工姓名'||r_job.ENAME);
    end loop;
end;
SELECT * FROM EMP
--6:用更新游標(biāo)來(lái)為雇員加傭金:(用if實(shí)現(xiàn),創(chuàng)建一個(gè)與emp表一摸一樣的emp1表,對(duì)emp1表進(jìn)行修改操作),并將更新前后的數(shù)據(jù)輸出出來(lái) 
--http://zheng12tian.iteye.com/blog/815770 
    create table emp1 as select * from emp;
declare
    cursor
    csr_Update
    is
    select * from emp1 for update OF SAL;
    empInfo csr_Update%rowtype;
    saleInfo emp1.SAL%TYPE;
begin
  FOR empInfo IN csr_Update LOOP
   IF empInfo.SAL1500 THEN
    saleInfo:=empInfo.SAL*1.2;
    elsif empInfo.SAL2000 THEN
    saleInfo:=empInfo.SAL*1.5;
    elsif empInfo.SAL3000 THEN
    saleInfo:=empInfo.SAL*2;
   END IF;
   UPDATE emp1 SET SAL=saleInfo WHERE CURRENT OF csr_Update;
   END LOOP;
END;
--7:編寫(xiě)一個(gè)PL/SQL程序塊,對(duì)名字以‘A'或‘S'開(kāi)始的所有雇員按他們的基本薪水(sal)的10%給他們加薪(對(duì)emp1表進(jìn)行修改操作)
declare 
   cursor
   csr_AddSal
   is
   select * from emp1 where ENAME LIKE 'A%' OR ENAME LIKE 'S%' for update OF SAL;
   r_AddSal csr_AddSal%rowtype;
   saleInfo emp1.SAL%TYPE;
begin
   for r_AddSal in csr_AddSal loop
     dbms_output.put_line(r_AddSal.ENAME||'原來(lái)的工資:'||r_AddSal.SAL);
     saleInfo:=r_AddSal.SAL*1.1;
     UPDATE emp1 SET SAL=saleInfo WHERE CURRENT OF csr_AddSal;
   end loop;
end;
--8:編寫(xiě)一個(gè)PL/SQL程序塊,對(duì)所有的salesman增加傭金(comm)500
declare
   cursor
     csr_AddComm(p_job nvarchar2)
   is
     select * from emp1 where  JOB=p_job FOR UPDATE OF COMM;
   r_AddComm emp1%rowtype;
   commInfo emp1.comm%type;
begin
  for r_AddComm in csr_AddComm('SALESMAN') LOOP
    commInfo:=r_AddComm.COMM+500;
     UPDATE EMP1 SET COMM=commInfo where CURRENT OF csr_AddComm;
  END LOOP;
END;
--9:編寫(xiě)一個(gè)PL/SQL程序塊,以提升2個(gè)資格最老的職員為MANAGER(工作時(shí)間越長(zhǎng),資格越老)
--(提示:可以定義一個(gè)變量作為計(jì)數(shù)器控制游標(biāo)只提取兩條數(shù)據(jù);也可以在聲明游標(biāo)的時(shí)候把雇員中資格最老的兩個(gè)人查出來(lái)放到游標(biāo)中。)
declare
  cursor crs_testComput
  is
  select * from emp1 order by HIREDATE asc;
  --計(jì)數(shù)器
  top_two number:=2;
  r_testComput crs_testComput%rowtype;
begin
  open crs_testComput;
    FETCH crs_testComput INTO r_testComput;
     while top_two>0 loop
       dbms_output.put_line('員工姓名:'||r_testComput.ENAME||' 工作時(shí)間:'||r_testComput.HIREDATE);
       --計(jì)速器減一
       top_two:=top_two-1;
       FETCH crs_testComput INTO r_testComput;
      end loop;
   close crs_testComput;
end;
--10:編寫(xiě)一個(gè)PL/SQL程序塊,對(duì)所有雇員按他們的基本薪水(sal)的20%為他們加薪,
--如果增加的薪水大于300就取消加薪(對(duì)emp1表進(jìn)行修改操作,并將更新前后的數(shù)據(jù)輸出出來(lái)) 
declare
  cursor
    crs_UpadateSal
  is
    select * from emp1 for update of SAL;
    r_UpdateSal crs_UpadateSal%rowtype;
    salAdd emp1.sal%type;
    salInfo emp1.sal%type;
begin
    for r_UpdateSal in crs_UpadateSal loop
      salAdd:= r_UpdateSal.SAL*0.2;
      if salAdd>300 then
       salInfo:=r_UpdateSal.SAL;
       dbms_output.put_line(r_UpdateSal.ENAME||': 加薪失敗。'||'薪水維持在:'||r_UpdateSal.SAL);
       else 
       salInfo:=r_UpdateSal.SAL+salAdd;
       dbms_output.put_line(r_UpdateSal.ENAME||': 加薪成功.'||'薪水變?yōu)椋?||salInfo);
      end if;
      update emp1 set SAL=salInfo where current of crs_UpadateSal;
    end loop;
end;
--11:將每位員工工作了多少年零多少月零多少天輸出出來(lái)  
--近似
 --CEIL(n)函數(shù):取大于等于數(shù)值n的最小整數(shù)
 --FLOOR(n)函數(shù):取小于等于數(shù)值n的最大整數(shù)
 --truc的用法 http://publish.it168.com/2005/1028/20051028034101.shtml
declare
 cursor
  crs_WorkDay
  is
  select ENAME,HIREDATE, trunc(months_between(sysdate, hiredate) / 12) AS SPANDYEARS,
    trunc(mod(months_between(sysdate, hiredate), 12)) AS months,
    trunc(mod(mod(sysdate - hiredate, 365), 12)) as days
  from emp1;
 r_WorkDay crs_WorkDay%rowtype;
begin
  for  r_WorkDay in crs_WorkDay loop
  dbms_output.put_line(r_WorkDay.ENAME||'已經(jīng)工作了'||r_WorkDay.SPANDYEARS||'年,零'||r_WorkDay.months||'月,零'||r_WorkDay.days||'天');
  end loop;
end;
--12:輸入部門(mén)編號(hào),按照下列加薪比例執(zhí)行(用CASE實(shí)現(xiàn),創(chuàng)建一個(gè)emp1表,修改emp1表的數(shù)據(jù)),并將更新前后的數(shù)據(jù)輸出出來(lái)
-- deptno raise(%)
-- 10   5%
-- 20   10%
-- 30   15%
-- 40   20%
-- 加薪比例以現(xiàn)有的sal為標(biāo)準(zhǔn)
--CASE expr WHEN comparison_expr THEN return_expr
--[, WHEN comparison_expr THEN return_expr]... [ELSE else_expr] END
declare
   cursor
     crs_caseTest
     is
     select * from emp1 for update of SAL;
     r_caseTest crs_caseTest%rowtype;
     salInfo emp1.sal%type;
   begin
     for r_caseTest in crs_caseTest loop
     case 
      when r_caseTest.DEPNO=10
      THEN salInfo:=r_caseTest.SAL*1.05;
      when r_caseTest.DEPNO=20
      THEN salInfo:=r_caseTest.SAL*1.1;
      when r_caseTest.DEPNO=30
      THEN salInfo:=r_caseTest.SAL*1.15;
      when r_caseTest.DEPNO=40
      THEN salInfo:=r_caseTest.SAL*1.2;
     end case;
     update emp1 set SAL=salInfo where current of crs_caseTest;
    end loop;
end;
--13:對(duì)每位員工的薪水進(jìn)行判斷,如果該員工薪水高于其所在部門(mén)的平均薪水,則將其薪水減50元,輸出更新前后的薪水,員工姓名,所在部門(mén)編號(hào)。
--AVG([distinct|all] expr) over (analytic_clause)
---作用:
--按照analytic_clause中的規(guī)則求分組平均值。
 --分析函數(shù)語(yǔ)法:
 --FUNCTION_NAME(argument>,argument>...)
 --OVER
 --(Partition-Clause>Order-by-Clause>Windowing Clause>)
   --PARTITION子句
   --按照表達(dá)式分區(qū)(就是分組),如果省略了分區(qū)子句,則全部的結(jié)果集被看作是一個(gè)單一的組
   select * from emp1
DECLARE
   CURSOR 
   crs_testAvg
   IS
   select EMPNO,ENAME,JOB,SAL,DEPNO,AVG(SAL) OVER (PARTITION BY DEPNO ) AS DEP_AVG
   FROM EMP1 for update of SAL;
   r_testAvg crs_testAvg%rowtype;
   salInfo emp1.sal%type;
   begin
   for r_testAvg in crs_testAvg loop
   if r_testAvg.SAL>r_testAvg.DEP_AVG then
   salInfo:=r_testAvg.SAL-50;
   end if;
   update emp1 set SAL=salInfo where current of crs_testAvg;
   end loop;
end;

總結(jié)

以上就是本文關(guān)于Oracle中游標(biāo)Cursor基本用法詳解的全部?jī)?nèi)容,希望對(duì)大家有所幫助,歡迎參閱:oracle數(shù)據(jù)庫(kù)導(dǎo)入導(dǎo)出命令解析、ORACLE SQL語(yǔ)句優(yōu)化技術(shù)要點(diǎn)解析、淺談oracle中單引號(hào)轉(zhuǎn)義等,有什么問(wèn)題可以隨時(shí)留言,感謝大家!

您可能感興趣的文章:
  • Oracle中觸發(fā)器示例詳解
  • 詳解oracle中通過(guò)觸發(fā)器記錄每個(gè)語(yǔ)句影響總行數(shù)
  • Oracle觸發(fā)器trigger詳解
  • Oracle觸發(fā)器用法實(shí)例詳解
  • oracle監(jiān)控某表變動(dòng)觸發(fā)器例子(監(jiān)控增,刪,改)
  • Oracle創(chuàng)建主鍵自增表(sql語(yǔ)句實(shí)現(xiàn))及觸發(fā)器應(yīng)用
  • Oracle存儲(chǔ)過(guò)程游標(biāo)用法分析
  • Oracle顯示游標(biāo)的使用及游標(biāo)for循環(huán)
  • 快速學(xué)習(xí)Oracle觸發(fā)器和游標(biāo)

標(biāo)簽:許昌 焦作 合肥 滁州 涼山 郴州 遼源 南充

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《Oracle中游標(biāo)Cursor基本用法詳解》,本文關(guān)鍵詞  Oracle,中,游標(biāo),Cursor,基本,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《Oracle中游標(biāo)Cursor基本用法詳解》相關(guān)的同類(lèi)信息!
  • 本頁(yè)收集關(guān)于Oracle中游標(biāo)Cursor基本用法詳解的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章