1. 程式人生 > >oracle學習總結------procedure

oracle學習總結------procedure





--子程式(儲存過程,函式)


--儲存過程
--語法:
 --create or replace procedure 儲存過程名字【(引數列)】
 --is|as
 --宣告區
  --begin
  --執行區
  --exception
  --異常處理
  --end;
  
  --儲存過程的引數分為三類 in, out, in out 引數型別不能帶長度
     --in是將實際引數傳給形參,預設型別
     --out是將形式引數傳遞給實參,可以實現多個值得返回
     -- in out 兩個兼備
     
  
  --例項:建立一個儲存過程,列印所有部門的編號和部門的平均工資


  create or replace procedure pro_get_sal is
  v_deptno emp.deptno%type;
  v_avg_sal emp.sal%type;
  cursor cur is select deptno,avg(nvl(sal,0)) from emp group by deptno; 
  begin
    open cur;
    fetch cur into v_deptno,v_avg_sal;
    while cur%found loop
      dbms_output.put_line('deptno=' || v_deptno ||'v_avg_sal=' || v_avg_sal);
       fetch cur into v_deptno,v_avg_sal;
      end loop;
      
   close cur;   
      
  end;
  
   --例項:建立一個儲存過程,列印所有部門的編號和部門的平均工資
  create or replace procedure pro_get_sal2 is
  begin
    for emp in(select deptno,avg(nvl(sal,0)) avg_sal from emp group by deptno) loop
       dbms_output.put_line('deptno=' || emp.deptno ||'v_avg_sal=' || emp.avg_sal); 
    
      end loop;
    end;
  
  
  
 declare 
  begin
    pro_get_sal2();
    end;
      
  
  
--建立一個儲存過程,引數傳入一個員工編號,列印該員工所在的職位的員工姓名和薪資


create or replace procedure get_jon_empty(eno in emp.empno%type)
is 
 
begin
     for e in ( select * from emp where job like(select job from emp where empno=eno) )loop 
    dbms_output.put_line(e.ename || ' ' || e.sal || '  ' || e.job);
     end loop;
  end;
      
   --呼叫儲存過程
   
   declare
   begin
     --pro_get_sal;
     get_jon_empty('&input');
   end;
   
  --刪除儲存過程
   drop procedure pro_get_sal;
   
   


   --查詢CLERK的所有員工資訊
   select * from(select * from emp where job='&input');
   
   --建立一個儲存過程,引數傳入一個員工編號,列印該員工所在的職位的員工姓名和薪資
   declare
   begin  
   for e in ( select * from emp where job like(select job from emp where empno='&input') )loop 
    dbms_output.put_line(e.ename || ' ' || e.sal);
     end loop;
     end;
     
   --建立一個儲存過程,引數傳入部門編號,輸出該部門的平均工資。
   
   create or replace procedure get_dept_sal(dno in emp.deptno%type,avg_sal out emp.sal%type)
   is
   begin  
     select avg(nvl(sal,0)) into avg_sal from emp where deptno = dno;
     end;
     
     
     declare 
      s emp.sal %type;
     begin 
       get_dept_sal('&input',s);
       dbms_output.put_line(s);
       end;
   
   
   
   
   --建立一個儲存過程,引數傳入一個員工編號,輸出該員工的姓名,
     --薪資,職位,用該職位作為引數建立儲存過程,用於查詢該職位的員工資訊
     
     
     --建立一個儲存過程,引數傳入一個員工編號,輸出該員工的姓名,薪資,職位,
     create or replace procedure get_emp_info(eno in emp.empno%type,
     v_name out emp.ename%type,v_sal out emp.sal%type,v_job out emp.job%type)
     as 
     begin
        select ename,sal,job into v_name,v_sal,v_job from emp where empno = eno;
       end;
   
   
    --建立一個儲存過程,用於引數傳入則職位,顯示該職位的所有員工資訊
    
     create or replace procedure prin_dept_info(v_job in emp.job%type)
     
     as
     
     begin 
  
          for temp in( select * from emp where job = v_job) loop
            dbms_output.put_line(temp.empno || '  ' || temp.ename || '  ' ||temp.job ||'  ' 
            ||to_char(temp.hiredate,'YYYY-MM-DD'));
            end loop;
      
       end;
       
     --建立一個儲存過程,用於引數傳入員工編號,和修改的薪資,修改emp的對應引數的員工的薪資
     
     create or replace procedure pro_setSal(in_empno in emp.empno%type,in_sal in emp.sal%type)
      is
      begin
     
      update emp set sal = in_sal  where empno = in_empno;
      exception
        when no_data_found then
          dbms_output.put_line('沒有該員工資訊');
        end; 
        
        --建立匿名塊,呼叫儲存過程
        declare
        begin
          pro_setSal(7369,1000);
          end;
      
      update emp set sal = 500 where empno =7369;  
      s+


    rollback;
   
 
   
   declare 
   v_name emp.ename%type;
   v_sal emp.sal%type;
   v_job emp.job%type;
   begin
     
   get_emp_info('&input',v_name ,v_sal,v_job);
    dbms_output.put_line(v_name || '  ' || v_sal || '  ' ||v_job);
    dbms_output.put_line('-----------------');
    prin_dept_info(v_job);
     end;
     
   
   
   --函式
   --基本語法
   --create or replace function 函式名【(引數列)】
   -- return 返回值型別 //返回值型別不能帶長度
   -- is|as
   --宣告區
   --begin
   --執行區,一定要有return語句
   --exceprion
   --異常區
   --end;
   
    
   -- in out 引數
   
   
 
   
   --CASE 條件表示式
  --WHEN 條件表示式結果1 THEN 
    -- 語句段1
  --WHEN 條件表示式結果2 THEN
    -- 語句段2
  --......
  --WHEN 條件表示式結果n THEN
    -- 語句段n
  --[ELSE 條件表示式結果]
--END;
---------格式二---------
--CASE 
  --WHEN 條件表示式1 THEN
    -- 語句段1
  --WHEN 條件表示式2 THEN
    -- 語句段2
  --......
  --WHEN 條件表示式n THEN 
    -- 語句段n
  --[ELSE 語句段]
--END;
   
  --例項:引數傳入兩個數,引數輸出他們的四則運算結構
   create or replace function operation(num1 number ,num2 number ,c char)
   return number
   is
   re number;
   begin
     case c 
       when '+' then
         re := num1 + num2;
       when  '-' then
         re := num1 - num2;
        when '*' then
         re := num1 * num2;
         when  '/' then
           re := num1/num2;
         dbms_output.put_line('re-->' + re);
         end case ;
     return re;
     end;
     
   declare
   
   begin
     
      dbms_output.put_line(operation(3 ,5 ,'*'));
     end;
     
     
     
     --案例:編寫一個函式,用於接收使用者名稱,和返回使用者的年薪
     
     create or replace function fun_annual_salary(v_in_empno number)
     return number is
     annual_sal number;
     begin
       select (sal + nvl(comm,0))*13 as an_sal into annual_sal  from emp where empno = v_in_empno;
       
       return annual_sal;
       exception
         when no_data_found then


        dbms_output.put_line('沒有該員工!');     
     end;
  




declare
an_sal emp.sal%type;
begin
  an_sal := fun_annual_salary(7369);
  dbms_output.put_line('年薪' || an_sal);
end;








--綜合例項,建立一個包,用於封裝儲存過程和函式,儲存過程用於修改員工的工資,函式用於獲得該員工的工資。


--定義包頭,用於宣告儲存過程和函式


create or replace package pak is
procedure pro(v_in_ename in varchar2,v_in_sal in number);
function fun(v_in_ename in varchar2) return number;
end;




--定義包體,用於定義儲存過程和函式


create or replace package body pak is


--定義儲存過程
procedure pro(v_in_ename in varchar2,v_in_sal in number) 
 is
begin 
  update emp set sal = v_in_sal where ename = v_in_ename;
  end;
    
--定義函式
function fun(v_in_ename in varchar2) return number
  is 
v_sal number;
 begin 
    select sal into v_sal from emp where ename = v_in_ename;
  return v_sal;
  end;  


end;




declare
v_sal number;
begin
  select pak.fun('KING')  into v_sal FROM dual;
  dbms_output.put_line(v_sal);
  end;
  
  
  
  
 --例項:建立一個儲存過程,用於引數輸入員工編號,引數輸出員工姓名和薪資,
 
 create or replace procedure proNameSal(v_in_empno in number , v_out_name out varchar2,v_out_sal out number)
 is 
 begin
   select ename,sal into v_out_name,v_out_sal from emp where empno = v_in_empno;
   end;
   
--建立一個匿名塊,用於呼叫儲存過程


declare
v_ename emp.ename%type;
v_sal number;
begin


  proNameSal(7839,v_ename,v_sal);
  dbms_output.put_line('name-->' ||v_ename || 'sal--->' || v_sal );
end;




--建立一個儲存過程,用於引數輸如部門編號,引數輸出該部門的所有員工資訊。


--1,定義一個包,用於定義一個遊標型別
create or replace package pack_cursor is
--定義一個動態遊標資料型別
 type dept_corsor is ref cursor;
 end;


--2.定義一個儲存,用於引數輸如部門編號,引數輸出該部門的所有員工資訊。
create or replace procedure pro_cursor(v_in_deptno in number,v_out_cursor out pack_cursor.dept_corsor)
 is
 --自定義異常
 nodata exception;
 begin
   --開啟動態遊標
   open v_out_cursor for select empno,ename,sal,deptno from emp where deptno = v_in_deptno;
   if v_out_cursor is null then 
     raise nodata;
     end if;
   --異常處理
   exception
     when nodata  then
        dbms_output.put_line('沒有該部門!');   
 end;
   
 
 --3.建立一個塊,用於測試儲存過程
 declare
  v_cursor pack_cursor.dept_corsor;
 v_deptno emp.deptno%type :=&input; 
 v_name emp.ename%type;
 v_empno emp.empno%type;
 v_sal emp.sal%type;
 begin
   pro_cursor(v_deptno,v_cursor);
   
   --執行遊標
   fetch v_cursor into v_empno,v_name,v_sal,v_deptno;
   while v_cursor%found loop
   dbms_output.put_line('員工編號:' || v_empno  || ' 員工姓名:' || v_name || ' 薪資:' ||v_sal || ' 所屬部門:' || v_deptno );
    fetch v_cursor into v_empno,v_name,v_sal,v_deptno;
   end loop; 
    --關閉遊標
   close v_cursor;
   end;
   
  
   




--sql語句實現分頁:
select t2.* from (select t1.*,rownum as rn from (select * from emp) t1 where rownum <=10) t2 where rn >= 5;




--例項:建立一個儲存過程,實現分頁功能:
create or replace procedure paging(v_in_table in varchar2 , v_in_currPage in number,v_in_pageSize in number ,v_out_count out number
 ,v_out_pageCount out number, v_resultCursor out pack_cursor.dept_corsor ) is
 v_start number; --開始的記錄
 v_end number;--結束的記錄
  v_sql_count varchar(50);
  v_sql_page varchar2(2000);
  v_count number ;-- 儲存總記錄數  
  v_pageSize number;--分頁顯示的記錄數
  v_currPage number;--當前頁數
  v_table varchar2(2000); --需要查詢的表明
 begin 
   v_sql_count := 'select count(*) from ' || v_in_table;--獲得記錄數目
  execute immediate  v_sql_count into v_count ;  
    v_out_count := v_count;
    v_currPage := v_in_currPage;
    v_pageSize :=v_in_pageSize;
    v_table := v_in_table;
   --獲得頁面總數  
   if mod(v_count,v_in_pageSize) = 0 then
     v_out_pageCount := v_count / v_pageSize;
   
     else
        v_out_pageCount := v_count / v_pageSize + 1;
       end if;
   --獲得當前頁面的記錄 
   v_start := v_pageSize *(v_currPage - 1) + 1;
   v_end := v_pageSize * v_currPage;  
   v_sql_page := 'select t2.* from (select t1.*,rownum as rn from (select empno,ename,sal,deptno from ' ||  v_table || ') t1 where rownum <= ' ||  v_end || ') t2 where rn >= '  || v_start;
   open v_resultCursor for v_sql_page;
   end;
   
   
   declare
   v_table varchar2(20):= '&input';
   v_out_count number;
   begin
    -- execute immediate  'select count(*) from ' || v_table into v_out_count ;
     dbms_output.put_line(v_out_count);
     end;