一、涉及內容
1.掌握存儲過程與函數的概念。
2.能夠熟練創建和調用存儲過程與函數。
二、具體操作
1.創建存儲過程,根據職工編號刪除scott.emp表中的相關記錄。
(1)以scott 用戶連接數據庫,然后為system 用戶授予delete 權限。
語句:
connect scott/tiger; grant delete on emp to system;
截圖:
(2)以system 用戶連接數據庫,創建存儲過程。
語句:
connect system/orcl1234; create or replace procedure delete_emp (id scott.emp.empno%type) is begin delete from scott.emp where empno=id; exception when others then dbms_output.put_line('errors'); end;
截圖:
(3)system 用戶調用delete_emp存儲過程。
語句:execute delete_emp(7369);
截圖:
(4)scott 用戶調用delete_emp存儲過程。
語句:
grant execute on delete_emp to scott; connect scott/tiger; execute system.delete_emp(7369);
截圖:
2.創建存儲過程,根據職工編號修改scott.emp表中該職工的其他信息。
(1) 創建新用戶,並授予權限。
connect system/orcl1234; create user u1 identified by abcdef; grant create session, create procedure to u1; grant select,update on scott.emp to u1;

(2) 以新用戶連接數據庫,創建存儲過程。
語句:
connect u1/abcdef; CREATE OR REPLACE PROCEDURE update_emp (no IN scott.emp.empno%TYPE,--引用emp表中的某字段的數據類型,必須對該表具有select權限 name IN scott.emp.ename%TYPE DEFAULT NULL, job1 IN scott.emp.job%TYPE DEFAULT NULL, mgr1 IN scott.emp.mgr%TYPE DEFAULT NULL, hiredate1 scott.emp.hiredate%TYPE DEFAULT NULL, salary scott.emp.sal%TYPE DEFAULT NULL, comm1 scott.emp.comm%TYPE DEFAULT NULL, deptno1 scott.emp.deptno%TYPE DEFAULT NULL ) IS BEGIN if name is not null then update scott.emp set ename=name where empno=no; end if; if job1 is not null then update scott.emp set job=job1 where empno=no; end if; if mgr1 is not null then update scott.emp set mgr=mgr1 where empno=no; end if; if hiredate1 is not null then update scott.emp set hiredate=hiredate1 where empno=no; end if; if salary is not null then update scott.emp set sal=salary where empno=no; end if; if comm1 is not null then update scott.emp set comm=comm1 where empno=no; end if; if deptno1 is not null then update scott.emp set deptno=deptno1 where empno=no; end if; EXCEPTION WHEN others THEN rollback; END; /
截圖:
(3) u1調用update_emp 過程。
語句: exec update_emp(7369,salary=>2000);
截圖:
3.創建存儲過程,根據指定的職工編號查詢該職工的詳細信息。
(1)創建存儲過程。
語句:
connect scott/tiger; create or replace procedure select_emp (no in scott.emp.empno%type, emp_information out varchar2) is r scott.emp%ROWTYPE; begin select * into r from scott.emp where empno=no; emp_information:=emp_information||r.ename||' '||r.job||' '||r.sal||' '||r.mgr|| ' '||r.hiredate||' '||r.comm||' '||r.deptno; exception when no_data_found then emp_information:='No person!'; when others then emp_information:='Error!'; End; /
截圖:
(2)調用存儲過程。
語句:
set serveroutput on declare info varchar2(50); begin select_emp(7369,info); dbms_output.put_line(info); end; /
截圖:
4.創建函數,根據給定的部門編號計算該部門所有職工的平均工資。
(1)創建函數。
語句:
create or replace function avg_sal (no scott.emp.deptno%type) return number is avgsal number(7,2); begin select avg(sal) into avgsal from scott.emp where deptno=no; if avgsal is not null then --因為上面的語句不觸發異常,因此用if語句判斷是否查詢成功 return avgsal; else avgsal:=-1; return avgsal; end if; end avg_sal; /
截圖:
(2)調用函數。
語句:
begin dbms_output.put_line(avg_sal(&deptno)); end;
截圖:
(選擇題)
- 以下哪種程序單元必須返回數據?( A )
A.函數 B.存儲過程 C.觸發器 D.包
2.當建立存儲過程時,以下哪個關鍵字用來定義輸出型參數?( C )
A.IN B.PROCEDURE C.OUT D.FUNCTION
3.下列哪個語句可以在SQL*Plus中直接調用一個存儲過程?( B )
A.RETURN B.EXEC C.SET D.IN
4.下面哪些不是存儲過程中參數的有效模式?( D )
A.IN B.OUT C.IN OUT D.OUT IN
5.函數頭部中的RETURN語句的作用是什么?( A )
A.聲明返回的數據類型
B.調用函數
C.調用過程
D.函數頭部不能使用RETURN語句
(編程題)
- 根據以下要求編寫存儲過程:輸入部門編號,輸出scott.emp 表中該部門所有職工的職工編號、姓名、工作崗位。
(1)授予system用戶對scott.emp具有顯示的查詢權限。
(2)創建存儲過程
語句:
create or replace procedure pro_depart (no in scott.emp.deptno%type) is cursor c1 is select * from scott.emp where deptno=no; begin dbms_output.put_line('編號 姓名 工作崗位'); for rec in c1 loop dbms_output.put_line(rec.empno||' '||rec.ename||' '||rec.job); end loop; end;
截圖:
(3)執行存儲過程
語句: execute pro_depart(20);
截圖:
2.根據以下要求編寫函數:將scott.emp 表中工資低於平均工資的職工工資加上200,並返回修改了工資的總人數。
(1)授予system用戶對scott.emp具有修改的權限。
(2)創建函數
語句:
conn system/orcl1234; create or replace function fun_sal return number is cursor c2 is select * from scott.emp for update; rows number default 0; avg_sal number(7,2); begin select avg(sal) into avg_sal from scott.emp; for rec in c2 loop if rec.sal< avg_sal then update scott.emp set sal=sal+200 where current of c2; rows:=rows+1; end if; end loop; return rows; end;
截圖:
(3)調用函數
語句:
begin dbms_output.put_line('修改了工資的總人數是: '||fun_sal); end;
截圖:
(簡答題)
創建與調用存儲過程或函數時,應事先授予哪些權限?
答:1.首先創建存儲過程自身需要的權限,即應授予create procedure系統權限。
2.用戶調用其他用戶所創建的存儲過程時,應事先授予對該過程的execute權限。
3.如果對某表進行增、刪、查、改的操作時,應授予insert、delete、update、select的顯示權限。
(補充練習題)
1. 編寫函數get_salary,根據emp表中的員工編號,獲取他的工資。輸入參數為員工編號,如果找到該員工,屏幕顯示已找到的信息,函數返回值為該員工的工資。如果找不到,捕獲並處理異常,函數返回值為0。函數創建成功后,調用該函數查看效果。
(1)創建函數
語句:
create or replace function get_salary (no in scott.emp.empno%type) return number is salary scott.emp.sal%type; begin select sal into salary from scott.emp where empno=no; return salary; exception when others then return 0; end;
截圖:
(2)調用函數
語句:
begin dbms_output.put_line('該員工工資是:'||get_salary(7369)); end;
截圖:
語句:
begin dbms_output.put_line('該員工工資是:'||get_salary(2000)); end;
截圖:
2. 編寫函數get_cnt,根據輸入參數部門編號,輸出參數輸出該部門的人數,返回值是該部門的工資總和。如果如果找不到,捕獲並處理異常,函數返回值為0。函數創建成功后,調用該函數查看效果。
(1)創建函數
語句:
create or replace function get_cnt (no in scott.dept.deptno%type, cnt out number ) return number is salary_sum number(7,2); begin select sum(sal) into salary_sum from scott.emp where deptno=no; select count(*) into cnt from scott.emp where deptno=no; return salary_sum; exception when others then return 0; end;
截圖:
(2)調用函數
語句:
var salary_sum number; var cnt number; exec :salary_sum:=get_cnt(30,:cnt);
截圖:
3.編寫存儲過程DelEmp,刪除emp表中指定員工記錄。輸入參數為員工編號。如果找到該員工,則刪除他的記錄,並在屏幕顯示該員工被刪除。如果沒找到,則使用自定義異常處理。存儲過程定義成功后,調用該存儲過程查看結果。
(1)以scott 用戶連接數據庫,然后為system 用戶授予delete 權限。
語句:
connect scott/tiger; grant delete on emp to system;
截圖:
(2)以system 用戶連接數據庫,創建存儲過程。
語句:
connect system/orcl1234; create or replace procedure DelEmp (no scott.emp.empno%type) is no_emp exception; cnt number; begin select count(*) into cnt from scott.emp where empno=no; if cnt=0 then raise no_emp; end if; delete from scott.emp where empno=no; dbms_output.put_line(no||'號員工已經被刪除完畢!'); exception when no_emp then dbms_output.put_line('抱歉!沒有找到'||no||'號員工!'); end; /
截圖:
(3)調用存儲過程。
語句:exec DelEmp(2000);
截圖:
4. 編寫存儲過程QueryEmp,查詢指定員工記錄;輸入參數為員工編號,輸出參數是員工的姓名和工資。如果找到該員工,在屏幕顯示該員工已經查到。如果沒找到,則捕獲異常並處理。存儲過程定義成功后,調用該存儲過程查看結果。
(1)創建過程
語句:
CREATE OR REPLACE PROCEDURE QueryEmp (no IN scott.emp.empno%TYPE, name OUT scott.emp.ename%TYPE, salary OUT scott.emp.sal%TYPE) IS BEGIN SELECT ename,sal into name,salary FROM scott.emp WHERE empno=no; dbms_output.put_line('找到員工!'); EXCEPTION WHEN NO_DATA_FOUND THEN dbms_output.put_line('該職工不存在!'); END; /
截圖:
(2)執行過程
語句:
DECLARE emp_name scott.emp.ename%TYPE; emp_salary scott.emp.sal%TYPE; BEGIN QueryEmp(7788,emp_name,emp_salary); --調用存儲過程 IF emp_name IS NOT NULL THEN --如果該職工存在,則輸出 dbms_output.put_line('姓名是:'||emp_name|| ' 工資是:'||emp_salary); END IF; END;
亦可:exec QueryEmp(7788,:ename,:sal);
截圖:
來源:https://www.cnblogs.com/shenxiaolin/p/5518824.html