一、函数或过程的选择
1.如果要进行DML(增删改),选择存储过程
2.如果没有DML,选择函数
二、函数
1.格式
create or replace function 函数名(参数1 类型,参数2 类型, 。。。)
return 类型
is
--变量声明区
begin
--业务逻辑区
return 值;
end;
/
2.实例
--练习,山寨sign函数:
--逻辑:判断某一个数,如果>0,就返回1,
--如果<0,返回-1,如果=0,就返回0;
create or replace function sgn(a number)
return number
is
begin
if a>0 then
return 1;
elsif a=0 then
return 0;
else
return -1;
end if;
end;
/
--select sgn(5) from dual;
declare
res number;
begin
res:=sgn(10);
if res>0 then
dbms_output.put_line('正数');
end if;
end;
/
--练习:比较两个员工的工资高低
create or replace function sgnsal(id1 number,id2 number)
return number
is
sal1 number;
sal2 number;
begin
select sal into sal1 from emp where empno=id1;
select sal into sal2 from emp where empno=id2;
if sal1>sal2 then
return 1;
elsif sal1=sal2 then
return 0;
else
return -1;
end if;
end;
/
declare
res number;
begin
res:=sgnsal(7369,7788);
if res=1 then
dbms_output.put_line('前面的大');
elsif res=0 then
dbms_output.put_line('一样大');
else
dbms_output.put_line('后面的大');
end if;
end;
/
--练习:根据部门号计算部门的总工资
create or replace function total(dno number)
return number
is
totalsal number;
begin
select sum(sal) into totalsal from emp where deptno=dno;
return totalsal;
end;
/
select total(10) from dual;
函数的参数类型也和存储过程一样规则
--练习:返回两个数a,b的和,并返回这两个数
create or replace function abtotal(a in out number,b in out number)
return number
is
begin
if a is null then
a:=1;
end if;
if b is null then
b:=1;
end if;
return a+b;
end;
/
declare
total number;
a number;
b number:=10;
begin
total:=abtotal(a,b);
dbms_output.put_line(total);
dbms_output.put_line(a);
dbms_output.put_line(b);
end;
/
三、触发器
1.定义:是ORACLE在发生某些事件时,可以自动触发并调用的PLSQL程序,可以定义在事件上,由事件自动触发。
2.分类:
(1)系统触发器
由系统时间触发的PLSQL程序,比如登录ORACLE\登出ORACLE
(2)DML触发器
由DML语句触发的PLSQL程序,如增删改
3.DML触发器
(1)语句级触发器
如果执行完一条DML语句后,希望对整张表的数据进行预算,使用语句级触发器, 这种触发器是在DML执行前/执行后触发的。
--格式:
--注意:触发器是自己调用的,不需要调用
create or replace trigger 触发器名
before|after insert|update|delete on 表
declare
声明变量
begin
处理业务
end;
/
--练习:在进行任何增删改操作后,计算出员工数,员工总薪资,员工平均工资
create or replace trigger mmp
after insert or update or delete on emp
declare
countEmp number;
totalSal number;
avgSal number;
begin
select count(*),sum(sal),trunc(avg(sal),2) into countEmp,totalSal,avgSal from emp;
dbms_output.put_line('总人数 '||countEmp);
dbms_output.put_line('总工资 '||totalSal);
dbms_output.put_line('平均工资'||avgSal);
end;
/
update emp set sal=2500 where empno=7369;
drop trigger mmp;
(2)行级触发器
如果在执行DML时,希望对当前操作的数据进行处理,那么可以使用行级触发器,行级触发器也是在执行DML之前/之后自动触发的,在行级触发器中可以使用行变量,引用到DML所操作的数据,这个行变量是内置的,可以直接使用。
行变量
:new 表示引用的是新增后的行数据
:old 表示引用的是修改/删除前的行数据
规则
insert语句只有:new,表示插入后的新数据
delete语句只有:old,表示删除前的旧数据
update语句既有:new也有:old,其中
:new表示修改后的数据,
:old表示修改前的数据
--格式:
create or replace trigger 触发器名
before|after insert|update|delete on 表
for each row
declare
声明变量
begin
处理业务
end;
/
--用法:
--变量名.字段名
--触发器中不能写commit
--练习:删除dept表数据之前,将删除记录存入备份表中
create or replace trigger tri_dept
before delete on dept
for each row
declare
begin
insert into dept_bak values(:old.deptno,:old.dname,:old.loc);
end;
/
delete from dept;
select * from dept_bak;
rollback;
--练习:修改员工工资,显示一下之前和之后的工资
set serveroutput on;
create or replace trigger tri_sal
after update on emp
for each row
declare
begin
dbms_output.put_line('old='||:old.sal||',new='||:new.sal);
end;
/
update emp set sal=4000 where empno=7369;