Oracle实战练习(续四)

#1.PL/SQL
 #PL/SQL是Oracle内部使用的编程语言, Procedure Language过程语言,其语言格式比较固定
 begin
   dbms_output.put_line('HelloWorld');
 end; 
 /   #/表示执行
 set serveroutput on;   #执行输出命令,默认是off(关闭)

 declare  #声明变量
   v_name varchar2(20);
   begin
     v_name := 'myname';    #给变量赋值
     dbms_output.putline(v_name);
   end;
   / 
  #打印:myname, 输出myname
  #PL/SQL过程已成功完成  
 
 declare
  v_name number:= 0;
 begin
  v_name := 2/v_name;
  dbms_output.put_line(v_name);
  exception
   when others then
    dbms_output.put_line('error');
 end;
 /
 #去掉exception语句块
 declare
  v_name number:= 0;
 begin
  v_name := 2/v_name;
  dbms_output.put_line(v_name);
 end;
 /
 #则会出现如下错误:除数为 0 在 line 4
 
 #2.变量声明
     #变量名不能使用保留字,如from, select等
     #第一个字符必须是字母
     #变量名最多包含30个字符
     #不要与数据库的表或者列同名
     #每一行只能声明一个变量
 #3.常用变量类型
     #binary_integer: 整数,主要用来计数而不是用来表示字段类型  
     #number : 数字类型
     #char: 定长字符串
     #varchar2: 变长字符串
     #date: 日期
     #long: 长字符串, 最长2GB
     #boolean :布尔类型, 可以取值为true, false和null值.
    
 declare
   v_temp number(1);
   v_count binary_integer := 0;   --binary_integer 是用来记数的,效率比较高一点.
   v_sal number(7,2) := 4000.00;
   v_date date := sysdate;
   v_pi constant number(3,2) := 3.14;
   v_valid boolean := false;
   v_name varchar2(20) not null := 'MyName';
  begin
   dbms_output.put_line('v_temp value: ' || v_date);
  end;
 
 #4.变量声明,使用%type属性
  declare
    v_empno number(4);
    v_empno2 emp.empno%type;  --表示emp表中empno的类型
    v_empno3 v_empno2%type;
   begin
     dbms_output.put_line('Test');
   end; 
 
  --Table 变量类型
  declare
    type type_table_emp_empno is table of emp.empno%type index by binary_integer;
    v_empnos type_table_emp_empno;
   begin
     v_empnos(0):=7369;
     v_empnos(2):=7839;
     v_empnos(-1):= 9999;             
     dbms_output.put_line(v_empnos(-1));
   end; 
  
  --Record变量类型 (相当于java中的类(class))
   declare
     type type_record_dept is record
      (
       deptno dept.deptno%type,
       dname dept.dname%type,
       loc dept.loc%type
      ) ;
     v_temp type_record_dept;  --声明变量是type_record_dept类型
    begin
      v_temp.deptno :=50;   --引用类型的属性
      v_temp.dname := 'aaaa';   
       v_temp.loc := 'bj';
       dbms_output.put_line(v_temp.deptno||' '|| v_temp.dname);
    end;
    /
 --record类型是指定义了一个类,然后引用类中的属性.
 
 --使用%rowtype声明record变量
 declare
   v_temp dept%rowtype;
 begin
   v_temp.deptno := 50;
   v_temp.dname := 'aaa';
   v_temp.loc := 'bj';
   dbms_output.put_line(v_temp.deptno ||'  ' ||v_temp.dname);
 end;
 /    
 --可以保留原来的类型
 
 --PL/SQL语句,必须返回一条记录,只能返回一条记录.
 
 --SQL语句的运用
 declare
   v_ename emp.ename%type;
   v_sal emp.sal%type;
 begin
   select ename, sal into v_ename, v_sal from emp where empno = 7369; --把ename中的记录赋值给v_ename,sal赋值给v_sal.
   dbms_output.put_line(v_ename ||' '||v_sal);
 end;
 / 
 --结果: SMITH 800
 declare
   v_ename emp.ename%type;
   v_sal emp.sal%type;
 begin
   select ename, sal into v_ename, v_sal from emp where empno = 9999;
   dbms_output.put_line(v_ename ||' '||v_sal);
 end;
 / 
   --如果未找到数据
  
 declare
   v_sal emp.sal%type;
 begin
   select sal into v_sal from emp
      where empno = 7369;
      if(v_sal<1200) then
         dbms_output.put_line('low');
      elsif(v_sal<2000) then
         dbms_output.put_line('middle');
      else
         dbms_output.put_line('high');
      end if;
  end;              
 
  set serveroutput on;
  
  declare
    v_sal2 emp.sal%type;
  begin
     select sal into v_sal2 from emp where empno = 7839;  
      if(v_sal2>2500) then
          v_sal2 := v_sal2 / 2; 
      elsif(v_sal2<2500) then
          v_sal2 := v_sal2 * 2;
      else
          v_sal2 := 2500;  
      end if;
  end;             
  
  --循环
  --loop循环
  declare
    i binary_integer:=1;
  begin
    loop
     dbms_output.put_line(i);
      i := i+1;
      exit when(i>=11);
    end loop;
  end;    
  
  --while循环
 declare
   j binary_integer :=1;
 begin
   while (j<11) loop
    dbms_output.put_line(j);
     j := j +1;
   end loop;
 end; 
 
 --for 循环
 begin
   for k in 1..10 loop
    dbms_output.put_line(k);
   end loop;
   for k in reverse 1..10 loop
    dbms_output.put_line(k);
   end loop;
 end;     
     
 --错误处理
 declare
  v_temp number(4);
 begin
  select empno into v_temp from emp where deptno = 10;
 exception
   when too_many_rows then
     dbms_output.put_line('太多记录');
   when others then
     dbms_output.put_line('error');
 end;  
 
 declare
  v_temp number(4);
 begin
   select empno into v_temp from emp where empno = 2222;
 exception
    when no_data_found then
     dbms_output.put_line('没数据');
  end;     
     
 --记录错误的做法
  create table errorlog
  (
    id number primary key,
    errcode number,
    errmsg varchar2(1024),
    errdate date
  );  
 
  create sequence seq_errorlog_id start with 1 increment by 1;        
   declare
     v_deptno dept.deptno%type := 10;
     v_errcode number;
     v_errmsg varchar2(1024);
  begin
    delete from dept where deptno = v_deptno;
    commit;
   exception
     when others then
      rollback;
      v_errcode := SQLCODE;
      v_errmsg := SQLERRM;
       insert into errorlog values(seq_errorlog_id.nextval, v_errcode, v_errmsg, sysdate);
     commit;
  end;
            
 select to_char(errdate, 'YYYY_MM_DD HH24:MI:SS') from errorlog;  
 
 --循环定义一个游标
 --游标是系统为用户开设的一个数据缓冲区,存放SQL语句的执行结果.每个游标区都有一个名字.
 --用户可以用SQL语句逐一从游标中获取记录,并赋给主变量,交由主语言进一步处理。主语言是面向记录的,一组主变量一次只能存放一条记录。
 declare
   cursor c is
    select * from emp;
    v_emp c%rowtype;
 begin
    open c;
     loop
        fetch c into v_emp;
        exit when(c%notfound);
        dbms_output.put_line(v_emp.ename);
    end loop;
  close c;
 end; 
 
 declare
   cursor c is
    select * from emp;
    v_emp emp%rowtype;
 begin
   open c;
    fetch c into v_emp;
     while(c%found) loop
     dbms_output.put_line(v_emp.ename);
      fetch c into v_emp;
     end loop;
   close c;
  end;    
    
 --带参数的游标
 declare
  cursor c (v_deptno emp.deptno%type, v_job emp.job%type) is
   select ename, sal from emp where deptno=v_deptno and job= v_job;
   --v_temp(%rowtype)
 begin
   for v_temp in c(30,'CLEAK') loop
   dbms_output.put_line(v_temp.ename);
  end loop;
end;    
         
 --可更新的游标
 declare
    cursor c is
       select * from emp2 for update;
  begin
    for v_temp in c loop
     if(v_temp.sal<2000)then
      update emp2 set sal= sal*2 where current of c; --更新当前游标,游标到哪条记录,更新哪条.
     elsif(v_temp.sal = 5000) then
      delete from emp2 where current of c;
     end if;
    end loop;
  commit;
 end;    
 
 --存储过程
 --(带有名字的PL/SQL的程序块)
 create or replace procedure p 
   is
     cursor c is
      select * from emp2 for update;
  begin
    for v_emp in c loop
      if(v_emp.deptno = 10) then
        update emp2 set sal= sal+10 where current of c;
      elsif(v_emp.deptno =20) then
        update emp2 set sal=sal+20 where current of c;
      else 
        update emp2 set sal=sal+30 where current of c ;
      end if;
    end loop;
  end;  
 --执行存储过程
 exec p;
 --查看结果集
 select sal from emp2;
 --或者
 begin p;
 end;
 --再执行了一次
 --查看结果集
 select sal from emp2;
 
 --带参数的存储过程
 create or replace procedure p1
  (v_a in number, v_b number, v_ret out number, v_temp in out number)
   is
    begin
      if(v_a>v_b) then
        v_ret :=v_a;
      else
        v_ret :=v_b;
      end if;
      v_temp:=v_temp+1;
    end;
 --调用过程
 declare
   v_a number :=3;
   v_b number :=4;
   v_ret number;
   v_temp number:=5;
 begin
   p(v_a, v_b, v_ret, v_temp);
   dbms_output.put_line(v_ret);
   dbms_output.put_line(v_temp);
 end; 
 --结果
 4
 6
 
 --删除存储过程
  drop procedure p;
 show error;   --显示错误.
 
 --函数(function)
 create or replace function sal_tax
   (v_sal number) return number
    is
    begin
      if(v_sal<2000)then
        return 0.10;
      elsif(v_sal<2750) then
        return 0.15;
      else
       return 0.20;
      end if;
    end;         
  -- 运用函数
  select lower(ename), sal_tax(sal) from emp;
 
  --触发器
  create table emp2_log
    (
      aname varchar2(20),
      action varchar2(10),
      atime date
     );
    
  create or replace trigger trig
    after insert or delete or update on emp2 for each row
   begin
     if inserting then
      insert into emp2_log values(USER,'insert',sysdate);
     elsif updating then
       insert into emp2_log values(USER,'update',sysdate);
     elsif deleting then
       insert into emp2_log values(USER,'delete',sysdate);
    end if;
  end;           
   
 update emp2 set sal= sal*2 where deptno=30;
 select * from emp2_log;
 update dept set deptno = 99 where deptno=10;#违反完整约束条件 (DYS.FK_DEPTNO),因为有外键参考.
 
 --删除触发器
 drop trigger trig;
 
 create or replace trigger trig
   after update on dept
     for each row
  begin
     update emp set deptno=:NEW.deptno where deptno=:OLD.deptno;
 end;    
 
  update dept set deptno=99 where deptno=10;
  select deptno from dept;
 
--树状结构的存储与展示
  drop table article;
  create table article
   (
     id number primary key,
     cont varchar2(4000),
     pid number,
     isleaf number(1),--0代表非叶子节点,1代表叶子节点.
     alevel number(2)
   ); 
  
  insert into article values(1,'蚂蚁大战大象',0,0,0);
  insert into article values(2,'大象被打趴下了',1,0,0);
  insert into article values(3,'蚂蚁也不好过',2,1,2);
  insert into article values(4,'瞎说',2,0,2);
  insert into article values(5,'没有瞎说',4,1,3);
  insert into article values(6,'怎么可能',1,0,1);
  insert into article values(7,'怎么没有可能',6,1,2);
  insert into article values(8,'可能性是很大的',6,1,2);
  insert into article values(9,'大象进医院了',2,0,2);
  insert into article values(10,'护士是蚂蚁',9,1,3);
 
  create or replace procedure p1(v_pid article.pid%type, v_level binary_integer)  is
    cursor c is select * from article where pid=v_pid;
   begin
     for v_article in c loop
       dbms_output.put_line(v_article.cont);
     
   
         
                                

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值