1.1什么是游標
用於臨時存儲一個查詢返回的多行數據(結果集,類似於java的jdbc連接返回的ResultSet集合),通過遍歷游標,可以逐行訪問處理該結果集的數據.
游標的使用方式: 聲明---打開--讀取---關閉
1.2語法
游標聲明:
CURSOR 游標名(參數列表) IS 查詢語句;
游標的打開:
OPEN 游標名
游標的取值:
FETCH 游標名 INTO 變量列表
游標的關閉:
CLOSE 游標名
1.3游標的屬性
游標的屬性 | 返回值類型 | 說明 |
%ROWCOUNT | 整型 | 獲取FETCH語句返回的數據行數 |
%FOUND | 布爾型 | 最近的FETCH語句返回一行數據則為真,否則為加 |
%NOTFOUND | 布爾型 | 與%FOUND屬性返回值相反 |
%ISOPEN | 布爾型 | 游標已經打開時值為真,否則為假 |
其中%NOTFOUND是在游標中找不到元素的時候返回TRUE,通常用來判斷退出循環
1.4創建和使用
示例:使用游標查詢emp表中的所有員工的姓名和工資,並將其依次打印出來
-- 使用游標查詢emp表中的所有員工的姓名和工資,並將其依次打印出來 declare -- 聲明游標 CURSOR 游標名(參數列表) IS 查詢語句; CURSOR c_emp IS select ename,sal FROM emp; --聲明變量接收游標中的數據 v_ename emp.ename%TYPE; v_sal emp.sal%TYPE; begin -- 打開游標 OPEN c_emp; --遍歷游標 LOOP --獲取游標中的數據 如果有的話賦值給變量 FETCH c_emp INTO v_ename,v_sal; EXIT WHEN c_emp%NOTFOUND; dbms_output.put_line('姓名:'||v_ename||',薪水:'||v_sal); END LOOP; --關閉游標 CLOSE c_emp; end;
1.5帶參數的游標
示例:使用游標查詢並打印某部門的員工的姓名和薪資,部門編號為運行時手動輸入.
-- 使用游標查詢並打印某部門的員工的姓名和薪資,部門編號為運行時手動輸入. declare -- 聲明游標 CURSOR 游標名(參數列表) IS 查詢語句; CURSOR c_emp(v_deptno emp.deptno%TYPE) IS select ename,sal FROM emp where deptno=v_deptno; --聲明變量接收游標中的數據 v_ename emp.ename%TYPE; v_sal emp.sal%TYPE; begin -- 打開游標 OPEN c_emp(20); --遍歷游標 LOOP --獲取游標中的數據 如果有的話賦值給變量 FETCH c_emp INTO v_ename,v_sal; EXIT WHEN c_emp%NOTFOUND; dbms_output.put_line('姓名:'||v_ename||',薪水:'||v_sal); END LOOP; --關閉游標 CLOSE c_emp; end;
給對應級別的員工漲工資,key是empno
-- 給對應級別的員工漲工資,key是empno declare -- 聲明光標 cursor cemp is select empno,job from emp; --聲明變量接收光標數據 pempno emp.empno%TYPE; pempjob emp.job%TYPE; begin -- 事務回滾 rollback; --打開光標 open cemp; loop --遍歷光標取出一個員工 fetch cemp into pempno,pempjob; --退出條件 exit when cemp%notfound; --判斷員工的職位 if pempjob='PRESIDENT' then update emp set sal=sal+1000 where empno=pempno; -- if condition then block ;elsif condition then block;else block;end if; elsif pempjob='MANAGER' then update emp set sal=sal+800 where empno=pempno; else update emp set sal=sal+400 where empno=pempno; end if; end loop; --關閉光標 close cemp; -- oracle的默認事務隔離級別是read committed --事務的ACID 原子性、一致性、隔離性、持久性 commit; end;
存儲過程和存儲函數
數據庫存儲過程:指存儲在數據庫中供所有用戶程序調用的子程序叫存儲過程、存儲函數
·相同點:完成特定功能的程序 ·不同點:是否用return語句返回值。存儲函數可以return返回值。存儲過程不可以通過return語句返回函數值。
1.創建存儲過程
create or replace procedure 過程名(參數列表) as begin ..........PLSQL子程序體; end;
2.執行存儲過程
--1.exec 存儲過程名(); --2.begin 存儲過程名(); end;
帶參數的存儲過程 舉例:為指定的員工,漲100塊錢的工資;並且打印漲前和漲后的薪水
1、創建一個帶參數的存儲過程: 給執行的員工漲100塊錢的工資,並且打印漲前和漲后的薪水
create or replace procedure raisesalary(eno in number) as --定義一個變量保存漲前的薪水 psal emp.sal%TYPE; begin --得到員工漲前的薪水 select sal into psal from emp where empno=eno; --給員工漲100 update emp set sal=sal+100 where empno=eno --需不需要commit? --注意:一般不在存儲過程或存儲函數中,commit和rollback --打印 dbms_output.put_line('漲前:'||psal||'漲后:'(pasl+100)) end; --2、如何調用: begin raisesalary(7839); raisesalary(7566); commit; end;
存儲過程的調試
1.調試存儲過程最好放到Oracle數據庫所在的系統或虛擬機上,解壓SQL developer ,雙擊運行。 2.為了確保存儲過程或函數是可調試的,右鍵“以編譯並進行調試”,點擊紅色按鈕“調試” 3.利用已寫好的調用函數進行調試。
1.函數的定義
是一個命名的存儲程序,可帶參數,並返回一個計算值。必須有return 子句,用於返回函數值。
2.創建存儲函數語法
create or replace function 函數名(參數列表) return 函數值類型 as begin PLSQL子程序體; end;
3.表達式中某個字段為空時,表達式返回值為空。為防止含有表達式的返回值錯誤,在可能為空的字段上加上NVL(字段名,0)。
--查詢某個員工的年收入
create or replace function queryemp_income(eno number) return number as --定義變量接收薪水和獎金 p_sal emp.sal%type; p_comm emp.comm%type; begin select sal,comm into p_sal,p_comm from emp where empno=eno; --nvl為遇空函數,如果p_comm為空則返回0 return nvl(p_comm,0)+p_sal*12; end;
1.存儲過程和存儲函數的區別
存儲函數可以有一個返回值,存儲過程沒有返回值
2.in out 參數
存過和函數都可以通過out 指定一個或多個輸出參數。可以利用out參數,實現多個返回值。
3.使用存過和存儲函數的原則
只有一個返回值的話,用存儲函數;否則,用存儲過程。
create or replace procedure query (eno in number, pename out varchar2, psal out number, pjob out varchar2 ) as begin select ename,sal,job into pename,psal,pjob from emp where empno=eno; end;