Oracle循环,存储过程和存储函数

create tablespace itheima51
datafile 'c:\itheima51.dbf'
size 100m
autoextend on
next 10m;

drop tablespace itheima51 including contents and datafiles;

select * from emp;
----条件表达式
----统计每份工作,在每个部门中的信息。
select job, deptno from emp;
----用条件表达式把deptno变成四列
select job,
       case deptno
         when 10 then '我属于10号部门'
           end "10号部门",
       case deptno
         when 20 then '我属于20号部门'
           end "20号部门",
       case deptno
         when 30 then '我属于30号部门'
           end "30号部门",
       case deptno
         when 40 then '我属于40号部门'
           end "40号部门"
from emp;

----在上面的基础之上按照job分组。
select job,
       count(case deptno
         when 10 then '我属于10号部门'
           end) "10号部门",
       count(case deptno
         when 20 then '我属于20号部门'
           end) "20号部门",
       count(case deptno
         when 30 then '我属于30号部门'
           end) "30号部门",
       count(case deptno
         when 40 then '我属于40号部门'
           end) "40号部门"
from emp
group by job;


----pl/sql编程语言:oracle对sql的封装,是sql具有过程化编程的特性。
-------让sql变得更加高效,灵活。
----declare begin end相当于java中的main方法。可以直接执行的方法。
declare
   i number(2) := 1;
   s varchar2(6) := '张三';
   en emp.ename%type;---引用型变量
   emprow emp%rowtype;---记录型变量
   isgood boolean := true;---不能直接输出,只能当条件用
begin
   dbms_output.put_line(i);
   dbms_output.put_line(s);
   select ename into en from emp where empno = 7788;
   dbms_output.put_line(en);
   select * into emprow from emp where empno = 7788;
   dbms_output.put_line(emprow.ename || '----' || emprow.job);
   if isgood then
     dbms_output.put_line('我是true');
   end if;
end;

-------if 用法
---输入小于18的数字,输出未成年,
---输入大于18小于40,输出中年人,
---输入大于40的数字,输出老年人。
declare
    i number(3) := ⅈ
begin
    if i<18 then
         dbms_output.put_line('未成年');
    elsif i<40 then
         dbms_output.put_line('中年人');
    else
         dbms_output.put_line('老年人');
    end if;
end;

-----loop
---用三种循环输出1到10十个数字
---while循环
declare
   i number(2) := 1;
begin
   while i<11 loop
      dbms_output.put_line(i);
      i := i+1;
   end loop;
end;
-----exit退出循环
declare
    i number(2) := 1;
begin
    loop
        exit when i>10;
        dbms_output.put_line(i);
        i := i+1;
    end loop;
end;
-----for循环
declare

begin
  for i in 1..10 loop
    dbms_output.put_line(i);
  end loop;
end;


----游标【光标】类似于java中的集合。
----输出emp表中所有员工的信息
declare
    cursor c1 is select * from emp;---定义一个游标类型变量c1并且赋值
    emprow emp%rowtype;--定义一个记录型变量。来存放c1中的每一行记录。
begin
    open c1;---打开游标
         loop
             fetch c1 into emprow;--用fetch在loop中取出c1的每一行数据,放在emprow中。
             exit when c1%notfound;---退出条件
             dbms_output.put_line(emprow.ename || '---' || emprow.job);
         end loop;
    close c1;---关闭游标
end;

-----用游标给指定部门员工涨工资
declare
    cursor c2(dno emp.deptno%type)
    is select empno from emp where deptno = dno;
    eno emp.empno%type;
    s emp.sal%type;
begin
    open c2(10);
        loop
             fetch c2 into eno;
             exit when c2%notfound;
             select sal into s from emp where empno = eno;
             dbms_output.put_line(s);
             update emp set sal=sal+100 where empno = eno;--类似java中调用数据库
             commit;
             select sal into s from emp where empno = eno;
             dbms_output.put_line(s);
        end loop;
    close c2;
end;


----例外,类似于java中的异常

declare
  i number(10);
begin
  i := 1/0;
exception
  when zero_divide then
     dbms_output.put_line('不能被0除。');
  when others then
     dbms_output.put_line('未知异常!');
end;

-----自定义异常
---查询指定部门的人,每个该部门没有人,抛出“该部门没有人”的异常。
declare
   cursor c3(dno emp.deptno%type)
   is select * from emp where deptno = dno;
   emprow emp%rowtype;
   no_data exception;---自定义异常
begin
   open c3(10);
       fetch c3 into emprow;---fetch不放在loop中,表示只取第一行
       if c3%notfound then
           raise no_data;---抛出自定义异常。
       end if;
   close c3;
exception
   when no_data then
     dbms_output.put_line('该部门没有人!');
end;


-----存储过程
----给指定员工涨一百块钱
create or replace procedure p1(eno emp.empno%type)
is
    s emp.sal%type;
begin
    select sal into s from emp where empno = eno;
    dbms_output.put_line(s);
    update emp set sal=sal+100 where empno = eno;
    commit;
    select sal into s from emp where empno = eno;
    dbms_output.put_line(s);
end;

---调用
declare

begin
  p1(7788);
end;


----存储函数
----计算指定员工的年薪
----参数和返回类型都不能加长度
create or replace function f_yearsal(eno emp.empno%type) return number
is
    ysarsal number(10);
begin
    select sal*12+nvl(comm, 0) into ysarsal from emp where empno = eno;
    return ysarsal;
end;

---调用
declare
  ysarsal number(10);
begin
  ysarsal := f_yearsal(7788);
  dbms_output.put_line(ysarsal);
end;

-----用存储过程算年薪
create or replace procedure p_yearsal(eno in emp.empno%type, yearsal out number)
is
  s emp.sal%type;
  c emp.comm%type;
begin
  select sal*12, nvl(comm,0) into s, c from emp where empno = eno;
  yearsal := s+c;
end;
-----调用
declare
  yearsal number(10);
begin
  p_yearsal(7788, yearsal);
  dbms_output.put_line(yearsal);
end;


----in,out的区别
----如果一个参数要做into或者:=赋值操作,必须为out的类型。
----如果该参数不做赋值操作,必须为in类型


----存储过程和存储函数的区别
----语法区别:关键字不一样,存储函数比存储过程多了两个return。
----特性区别:存储函数必须有返回值,存储过程可以没有返回值。
--------------我们可以用存储函数具有返回值的特性,来自定义函数。
----查询员工姓名和所在部门名称
select e.ename, d.dname
from emp e, dept d
where e.deptno = d.deptno;
----定义一个存储函数,输入部门编号,输出部门名称
create or replace function f_dept(dno dept.deptno%type) return varchar2
is
   dna dept.dname%type;
begin
   select dname into dna from dept where deptno = dno;
   return dna;
end;
----用自定义的函数f_dept来查询员工姓名和所在部门名称
select ename, f_dept(deptno) from emp;

-----用存储过程实现,输出指定部门员工信息
create or replace procedure p2(dno dept.deptno%type, dme out sys_refcursor)
is

begin
  open dme for select * from emp where deptno = dno;
end;
------调用p2
declare
  dme sys_refcursor;
  emprow emp%rowtype;
begin
  p2(10, dme);
     loop
        fetch dme into emprow;
        exit when dme%notfound;
        dbms_output.put_line(emprow.ename);
     end loop;
  close dme;
end;

------oracle10g用ojdbc14.jar
------oracle11g用ojdbc6.jar

------语句级触发器
----插入一行数据,显示新员工入职。
create or replace trigger t1
after
insert
on person
declare

begin
   dbms_output.put_line('新员工入职');
end;
---触发t1
select * from person;
truncate table person;
insert into person values (1, 'a');
commit;

-----行级触发器for each row
----不能给员工降薪
---raise_application_error(-20001~-20999不能重复, '错误提示信息');
create or replace trigger t2
before
update
on emp
for each row
declare

begin
  if :new.sal < :old.sal then
     raise_application_error(-20001, '不能给员工降薪');
  end if;
end;
----触发t2
update emp set sal = sal-100 where empno = 7788;
commit;

-----不能在礼拜天办理入职
create or replace trigger t3
before
insert
on person
declare
  d varchar2(10);
begin
  select trim(to_char(sysdate, 'day')) into d from dual;
  if d in ('sunday') then
    raise_application_error(-20002, '不能在礼拜天办理入职');
  end if;
end;

----触发t3
insert into person values (2, 'b');
commit;

select * from person;

-----用触发器,实现主键自增。
-----在做插入操作之前,拿到即将插入的数据对象:new,在该数据对象的pid上赋值。
create or replace trigger auto_pk
before
insert
on person
for each row
declare

begin
  select seq_person.nextval into :new.pid from dual;
end;

----使用auto_pk触发器自动给person表添加主键
insert into person values (1, 'a');
commit;
insert into person (pname) values ('a');
commit;

select * from person;

猜你喜欢

转载自blog.csdn.net/lyf_ldh/article/details/81140842