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;
相关文章
相关标签/搜索