Oracle存儲過程總結

  --例1:基本類型
declare 
   --變量類型:number、varchar二、char、date、binary_integer(索引)
  v_a number:=100;
  v_b varchar2(100) ; --字符串必須加長度
  v_d date:=sysdate;
  --動態追蹤表內數據類型
  v_ename emp.ename%type; --動態追蹤列類型
  v_emp_row emp%rowtype; --動態追蹤行類型
begin
  v_b := 'aaa';   --賦值語句
  dbms_output.put_line(v_a||'  '||v_b||'  '||v_d);
   --select  into 語句  賦值語句   語法:必須保證結果只有一條
  select e.ename into v_ename from emp e where e.empno=7369;
  select sum(e.sal) into v_a from emp e;
  dbms_output.put_line(v_ename||'  '||v_a);
  --使用行類型 
  select e.ename,e.hiredate,e.deptno into v_emp_row.ename,v_emp_row.hiredate,v_emp_row.deptno from emp e where e.empno=7369;
  select e.* into v_emp_row from emp e where e.empno = 7499;
  dbms_output.put_line(v_emp_row.ename||'  '||v_emp_row.hiredate);
 -- exception   
end;
--例2:異常
declare
  v_num number;
  v_num2 number;
begin
  select e.sal into v_num2  from emp e where e.empno=3333;
  exception
    /* when too_many_rows  then
      dbms_output.put_line('數據多啦');
    when no_data_found  then
      dbms_output.put_line('數據沒找到');*/
    when others then
       dbms_output.put_line('---------');
end;
--例3:if語句
declare 
  v_num1 number :=floor((dbms_random.value*6))+1;
  v_num2 number :=floor((dbms_random.value*6))+1;
  v_num3 number :=floor((dbms_random.value*6))+1;
  v_sum number := v_num1+v_num2+v_num3;
begin
   --搖色子  三個隨機數  求和   if 條件  then 語句; elsif 條件1 and/or 條件2 then 語句;...else 語句; end if; 
  if  v_sum >=12 then
    dbms_output.put_line('手氣不錯');
  elsif v_sum>=8 and v_sum <12  then
   dbms_output.put_line('手氣通常');
  else 
   dbms_output.put_line('手氣不好');
  end if;
end;
--例4:for循環
declare
  v_sum number:=0;
begin
   --for 變量 in 集合   loop  循環體; end loop;  變量不須要聲明 會動態匹配集合的單個元素的類型  v_r不能被賦值
  for v_r in 1..100  loop
    if mod(v_r,2)<>0 then 
     v_sum := v_sum+v_r;
    end if;
  end loop;
  dbms_output.put_line(v_sum);
  dbms_output.put_line('-----------------');
   for v_r in reverse 1..10  loop   --reverse  :逆序
    dbms_output.put_line(v_r);
  end loop; 
end;
--例5:loop循環
declare
  v_i number :=1;
  v_sum number :=0;
begin
  loop
    v_sum := v_sum + v_i;   --循環體
    exit when v_i>3;   --退出條件
    v_i := v_i+1;   --循環體
  end loop;
  dbms_output.put_line(v_sum);
end;
--例6:while循環 
declare 
  v_i number :=1;
  v_sum number :=0;
begin
  while v_i<=100 loop  --循環條件
     v_sum := v_sum+v_i;  --循環體開始
     v_i := v_i+1;
  end loop;
  dbms_output.put_line(v_sum);
end;
--例7:dml和ddl
declare 
begin
   -- dml 增刪改 能夠放結合事務處理, 不容許放查詢語句   ddl  create 語句  結合execute immediate 'ddl/dml';
  insert into emp_copy ec select * from emp e; 
  commit;
  execute immediate 'create table A(a_id number)';  --建立表語句加單引號
end;
--例8:Created on 2013-11-5 by ADMINISTRATOR 
declare 
--先定義類型   注意 內部多個變量 逗號隔開。
  type record_type is record(
       v_a number  not null :=100, --not null必須 初始化值
       v_ename emp.ename%type,  --列類型
       v_b varchar2(20)
  );
  --再綁定變量
  v_r record_type;
begin
  v_r.v_b :='aaa';
  select e.ename into v_r.v_ename from emp e where e.empno=7499;
  dbms_output.put_line(v_r.v_a||'   '||v_r.v_b||'   '||v_r.v_ename);
end;
--例9:table和複合類型
declare 
    --table相似於數組,使用步驟 :
   --1:定義類型
   type tab_type is table of varchar2(100) index by binary_integer;
    --2: 變量對應類型
   v_tab1 tab_type;
    --集中賦值的table語法後不加 index by
   type tab_type_2 is table of varchar2(100) ;
   v_tab2 tab_type_2;
begin
  -- 零散賦值 索引任意
  v_tab1(0) :='aaa';
  v_tab1(1) :='bbb';
  dbms_output.put_line(v_tab1(0)||'  '||v_tab1(1));
   --集中賦值  索引只能從1開始
  v_tab2 := tab_type_2('aaa','bbb','ccc');
  dbms_output.put_line(v_tab2(1)||'  '||v_tab2(2));
end;
--例10:簡單瞭解權限
create user 用戶名 identified by 密碼   --必須是管理員(dba)身份才能夠建立用戶
grant create session to stu;  --建立新用戶後須要  賦回話權限
grant create view to scott 
grant select,insert on emp to hr;  --on後跟的是表名
--切換到hr用戶,能夠正常對emp表執行select和insert操做。
--以後,再在Scott用戶下,收回hr對emp的權限
revoke all on emp from hr;
--賦予存儲過程debug權限
grant debug connect session to scott;
--例11: 不帶參數的存儲過程
create or replace procedure p_emp
is
begin
  insert into emp_copy(empno,ename) values(9999,'9999');
  commit;
  exception
    when others then
      rollback;
end;
例12:帶參數的存儲過程
--能夠寫參數  in 參數  out  參數 in 和out 能夠有多個
create or replace procedure p_emp_job(       --工做環境下不要加or replace
        l_empno in number,   -- in 能夠省略 最好寫上  不能被賦值
        l_job in out varchar2,   -- 通常 in  out 都分開寫
        l_sal out number
)
is
--此處聲明或初始化變量
begin
 select  e.sal , e.job into  l_sal , l_job  from  emp  e  where  e.empno=l_empno  and e.job=l_job;
   l_job := '7499';
end;  
--例13:調用參數存儲過程 
declare 
  v_job varchar2(20) :='CLERK';
  v_sal number;
begin
  p_emp_job(7369,v_job,v_sal);  --存儲過程名加參數
  dbms_output.put_line(v_job||'   '||v_sal);
end;  
--例14:顯示遊標
/**
 顯式遊標:
       靜態遊標: 聲明    打開    遍歷 (操做數據)  關閉;  推薦 for
       動態遊標:
            弱類型遊標:
            強類型遊標:
*/ 
declare 
    --聲明靜態遊標  能夠帶參數,參數類型後不加長度
  cursor  c_emp1 is select * from emp  e ;
  cursor  c_emp2(l_deptno number,l_job varchar2) is select * from emp  e where e.deptno=l_deptno and e.job=l_job;
  v_r  c_emp2%rowtype;  --行類型
begin
   --打開遊標  若是有參數  open時傳參 ,若是沒參數,不用寫。
  open c_emp2(20,'CLERK');
   --遍歷
  loop
    fetch c_emp2 into v_r;   --fetch 語句:至關於  next
  exit when c_emp2%notfound;
    dbms_output.put_line(v_r.ename);
  end loop;
  --關閉遊標
  close c_emp2;
   --靜態遊標推薦使用for   能夠自動打開和關閉遊標
  dbms_output.put_line('======================');
  for v_m in c_emp2(20,'CLERK')  loop
    dbms_output.put_line(v_m.ename);
  end loop;
  dbms_output.put_line('======================');
  --while爲啥很差使。
  open c_emp2(20,'CLERK');
   fetch c_emp2 into v_r;
  while c_emp2%found loop
     dbms_output.put_line(v_r.ename);
      fetch c_emp2 into v_r;
  end loop;
  close c_emp2;
end;  
--例14: 隱式遊標
/*遊標:
    隱式遊標:  sql語句  就是遊標 默認遊標的名字sql  (update/delete)事務提交後 遊標自動關閉。   
*/
declare 
begin
  -- Test statements here
  update emp_copy ec set ec.ename='aaa' where ec.deptno = 20;
  commit;
  if sql%notfound  then
    dbms_output.put_line('notfound');
  elsif sql%found  then
    dbms_output.put_line('found');
  end if;
end;  
--例15: 動態遊標之強類型
declare 
--強類型動態遊標
  type  c_emp is ref cursor return emp%rowtype;
  v_emp c_emp;
  v_emp_row v_emp%rowtype;
begin
  open  v_emp for select * from emp e;
  loop
    fetch v_emp into v_emp_row;
    exit when v_emp%notfound;
    dbms_output.put_line(v_emp_row.ename);
  end loop;
  close v_emp;  
end;  
--例16:動態遊標之弱類型
/*
動態遊標
    弱類型:
    強類型:
*/
declare 
  --先定義遊標類型   
 type c_emp is  ref cursor; 
  --綁定變量   此變量是遊標
  v_emp c_emp;
   --定義遊標 行類型
  v_emp_row emp%rowtype;
  v_dept_row dept%rowtype;
begin
  --打開遊標
  open v_emp for select * from emp e ;
  --遍歷遊標
  loop
    fetch v_emp into v_emp_row ;
    exit when v_emp%notfound;
    dbms_output.put_line(v_emp_row.ename);
  end loop;
   --關閉遊標
  close v_emp;
  --打開遊標 裝  dept的數據
  dbms_output.put_line('===================');
  open v_emp for select * from dept d;
  loop
    fetch v_emp into v_dept_row;
    exit when v_emp%notfound;
     dbms_output.put_line(v_dept_row.dname);
   end loop;
  close v_emp;
end;   
--例17: 使用遊標更新結果集 
declare 
--靜態遊標  select後加 for update 意味着結果集數據能夠更新
 cursor c_emp_copy is select * from emp_copy for update;
begin
  for v_r in c_emp_copy loop
    if v_r.deptno=20 then
      update emp_copy ec  set ec.ename='bbb' where current of c_emp_copy;
     -- update emp_copy ec set ec.ename='bbb' where ec.empno = v_r.empno;
    end if;
  end loop;
  commit;
  exception 
    when others then
      rollback;
end;
--例18:語句級觸發器  記錄信息時跟你操做多少條數據無關,只跟執行的語句有關。執行一次語句 觸發一次.
create or replace trigger tr_emp_copy
after insert or delete or update on emp_copy
begin
  if inserting then
        insert into emp_copy_log values(seq_emp_copy_log.nextval,user,sysdate,'inserting');
  elsif deleting then
        insert into emp_copy_log values(seq_emp_copy_log.nextval,user,sysdate,'deleting');
  elsif updating then
        insert into emp_copy_log values(seq_emp_copy_log.nextval,user,sysdate,'updating');
  end if;
   --觸發器事務不須要提交 或回滾,自動處理
end;
select * from emp_copy;
select * from emp_copy_log;
delete from emp_copy ec where ec.deptno=20;
commit;  
--例19:行級觸發器 (for each row) 用來維護數據完整性
select * from dept;
select * from emp ;
update dept d set d.deptno =10 where d.deptno=77;
commit;
--before  after區別 :能否修改 :new 的值(before能夠修改,after 不能夠修改)   二者對:old的值都不可修改
create or replace trigger tr_emp_dept 
before update on dept for each row 
begin
  update emp e  set e.deptno= :new.deptno where e.deptno = :old.deptno;
end;  
--例20:
instead of 觸發器
select * from v$_emp;
update v$_emp e set e.ename='aaa' where e.empno=2222;
commit;
select * from v$_emp_dept;
--組成視圖的表叫基表   一個視圖只有一個基表 只讀狀況下,不能夠修改。非只讀狀況下能夠修改數據
--若是一個視圖有多個基表,修改的字段牽扯到多個基表時,不能被修改,牽扯到1個基表,能夠修改.
update v$_emp_dept e set e.ename='ccc',e.dname='mmm' where e.empno=2222;
commit;
--instead of 觸發器
create or replace trigger tr_v$_emp_dept
instead of update on v$_emp_dept
begin
  update emp e set e.ename=:new.ename where e.empno=:old.empno;
  update dept d set d.dname=:new.dname  where d.deptno = :old.deptno;
end;  
--例21:寫一個存儲過程,能夠完成對 dept_copy表的增刪改
--debug步驟: 受權 sysdba下登錄 而後執行  grant debug connect session to 用戶名;
--回到用戶,選中存儲過程名 右鍵   選add debug ... 選 test  
create or replace procedure p_dept_copy(
       l_remark in number,    --0:add  1:update  2:delete
       l_deptno in number,
       l_dname in varchar2,
       l_loc in varchar2,
       l_result out number,   --0:失敗 1:成功 2:傳參錯誤
       l_result2 out varchar2 
)
is  
begin
      if l_remark=0 then--add
        insert into dept_copy  values(l_deptno,l_dname,l_loc);
      elsif l_remark=1  then--update
            update dept_copy  dc
            set 
                   dc.dname=l_dname,
                   dc.loc=l_loc
            where dc.deptno = l_deptno;
      elsif l_remark=2 then
            delete from dept_copy dc where dc.deptno = l_deptno;
      else
        l_result :=2;
        l_result2 :='傳參錯誤';
      end if;
      commit;
       --處理返回標記
       l_result:=1;
       l_result2:='成功';
       exception
         when others then
           rollback;
            l_result:=0;
            l_result2:='失敗';
end;  
--例22:函數
create or replace function f_str(
       l_str1 varchar2,
       l_str2 varchar2
)return varchar2   --此處不加分號 不加長度
is
begin
  return  l_str1 || l_str2;
end;  
--例23:select a.fid,f_a(fid) from A  group by fid;
create or replace function f_a(
          l_fid number
)return varchar2
is
  cursor c_a is select field1 from a where a.fid = l_fid;
  l_str varchar2(100);
begin
  for r in c_a loop
    l_str := l_str||r.field1||',';
  end loop;
  return rtrim(l_str,',');

end; 
sql

create or replace procedure test_pro(
       cur_customers out my_pac.cur_type --包裏定義遊標
)
is
begin
       open cur_customers for select * from customers;
end;
相關文章
相關標籤/搜索