Oracle數據庫—— 存儲過程與函數的創建


一、涉及內容

  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;

截圖:

 

 

(選擇題)

  1. 以下哪種程序單元必須返回數據?( 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語句

 

(編程題)

  1. 根據以下要求編寫存儲過程:輸入部門編號,輸出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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM