1、过程和函数简介
·过程和函数是命名的PL/SQL块,编译后可以存储在数据库中,以备执行。
其他PL/SQL块可以按名称来使用它们。
过程和函数也被称为子程序(subprogram)。
因为它们是单独的,能被父程序调用的一部分程序。
2、存储过程的特点
·过程是预编译过的,并且经过优化后存储与SQL内存中,
使用时无需再次编译,提高了工作效率;
·使用储存过程可以减少SQL注入式攻击,提高了系统的安全性,
执行存储过程的用户要具有一定的权限才能使用存储过程。
·使用存储过程,可以实现存储过程设计和编码工作分开进行,
只要将存储过程名,参数,及返回信息高速编码人员即可;
·使用存储过程封装业务逻辑将限制应用程序的可移植性,
更改存储过程比较繁琐。
3、存储过程的语法结构
·CREATE OR REPLACE PROCEDURE 存储过程名
IS|AS
声明语句段;
begin
执行语句段;
exception
异常处理语句段;
end 存储过程名;
4、存储过程的参数模式
·in模式的形参只能将实参传给形参,进入存储过程内部,
只能读不能写,返回的实参值不变
例子:
SQL> create or replace procedure proc(i in int)
2 as
3 a varchar(20);
4 begin
5 for j in 1..i loop
6 a:=a||'*';
7 dbms_output.put_line(a);
8 end loop;
9 end;
10 /
Procedure created
SQL> set serveroutput on;
SQL> exec proc(5);
*
**
***
****
*****
PL/SQL procedure successfully completed
注:打开命令窗口输出代码
set serveroutput on;
·out模式在存储过程内部可以读写,返回时形参的值会赋给形参
例子:
SQL> create or replace procedure proc(i out int)
2 as
3 begin
4 i:=100;
5 dbms_output.put_line(i);
6 end;
7 /
Procedure created
SQL> declare
2 a int;
3 begin
4 proc(a);
5 end;
6 /
100
PL/SQL procedure successfully completed
5、查看删除存储过程
·查看
select * from user_objects
·删除
drop procedure proc;
6、函数
·函数一般用于计算和返回一个值,可以将常用需要进行的计算写成函数。
7.函数语法
·CREATE [OR REPLACE] RUNCTION 函数名[(参数[IN] 数据类型..)]
RETURN 数据类型
{AS|IS}
[声明部分]
BEGIN
可执行部分
RETURN (表达式)
[EXCEPTION 异常处理部分]
END[函数名];
·PS:
·在定义部分的RETURN数据类型,用来表示函数的数据类型,
也就是返回值得类型,此部分不可忽略。
·在函数的执行部分可以有多个RETURN语句,但只有一个RETURN语句会被执行,
一旦执行了RETURN语句,则函数结束并返回调用环境
例子:
SQL> create or replace function fun1 return varchar2
2 is
3 begin
4 return 'hello,world!';
5 end;
6 /
Function created
SQL> declare
2 ss varchar2(20);
3 begin
4 ss:=fun1;
5 dbms_output.put_line(ss);
6 end;
7 /
hello,world!
·删除函数
drop function function_name ;
8、触发器概念
·触发器是响应插入,更新或删除等数据库事件而执行的过程。
它定义了当一些数据库相关事件发生时采取的动作。
触发器即用来监视数据库的各项操作。
9、触发器分类
·DML触发器
·INSTEAD OF 触发器
·系统触发器
10、DML触发器基本要点
·触发时机:指定触发器的触发时间
·触发事件:引起触发器触发的事件。即DML操作
·条件谓词:为了针对不同的事件进行不同的处理
·触发对象:触发器对应的表
·触发条件:由when指定一个逻辑表达式
·触发类型:指定触发事件语句级还是行级
·触发顺序:语句级(before、after)
11、DML触发器语法
·CREATE OR REPLACE TRIGGER trigger_name
{before|after}
{insert|delete|update[of column]...}
ON table_name
[FOR EACH ROW]
[WHEN codition]
例1:
SQL> create or replace trigger tri1
2 after insert
3 on emp
4 for each row
5 begin
6
dbms_output.put_line('触发器执行了');
7 end;
8 /
Trigger created
SQL> insert into emp(empno) values(7379);
触发器执行了
1 row inserted
例2:
SQL> create or replace trigger tri2
2 before insert
3 on emp
4 for each row
5 begin
6 if :new.empno<0 then //注::new.empno为变量要加冒号
7 raise_application_error(-20001,'员工编号为负,不能插入到表中!');
8 end if;
9 end;
10 /
Trigger created
SQL> insert into emp(empno) values(-1);
insert into emp(empno) values(-1)
ORA-20001: 员工编号为负,不能插入到表中!
ORA-06512: 在 "SCOTT.TRI2", line 3
ORA-04088: 触发器 'SCOTT.TRI2' 执行过程中出错
###########################练习#############################
1、自定义输入任意员工编号,输出该员工编号、姓名、工资、部门名称、所在地
SQL> declare
2 -- Local variables here
3 empno integer;
4 ename varchar2(20);
5 sal float;
6 dname varchar2(50);
7 loc varchar2(30);
8 i integer;
9 begin
10 -- Test statements here
11 select empno,ename,sal,dname,loc
12 into empno,ename,sal,dname,loc
13 from emp,dept where emp.deptno = dept.deptno and empno = &i;
14 dbms_output.put_line(empno||','||ename||','||sal||','||dname||','||loc);
15 end;
16 /
7369,SMITH,800,RESEARCH,DALLAS
PL/SQL procedure successfully completed
2、自定义输入任意员工编号,如果该员工入职时间大于10年,则奖金加1W,
该员工入职时间大于5年则奖金加5000,否则不加。
最终输出员工编号、姓名、入职时间,原奖金,现奖金
SQL> declare
2 -- Local variables here
3 empno integer;
4 ename varchar2(20);
5 hiredate scott.emp.hiredate%type;
6 wfs integer;
7 newcomm float;
8 oldcomm float;
9 i integer;
10 begin
11 -- Test statements here
12 i := &i;
13 select empno,
14 ename,
15 hiredate,
16 nvl(comm, 0),
17 trunc((sysdate - hiredate) / 365)
18 into empno, ename, hiredate, oldcomm, wfs
19 from emp
20 where empno = i;
21 if wfs > 10 then
22 newcomm := nvl(oldcomm, 0) + 10000;
23 update emp set comm = newcomm where empno = i;
24 elsif wfs > 5 then
25 newcomm := nvl(oldcomm, 0) + 5000;
26 update emp set comm = newcomm where empno = i;
27 end if;
-------commit;
28 dbms_output.put_line(empno || ',' || ename || ',' || hiredate || ',' ||
29 oldcomm || ',' || newcomm);
30 end;
31 /
7369,SMITH,17-12月-80,0,10000
PL/SQL procedure successfully completed
SQL> select * from emp where empno = 7369;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
----- ---------- --------- ----- ----------- --------- --------- ------
7369 SMITH CLERK 7902 1980/12/17 800.00 10000.00 20
5、对每位员工的薪水进行判断,如果该员工薪水高于其所在部门的平均薪水,
则将其薪水减50元,
SQL> /*5、对每位员工的薪水进行判断,如果该员工薪水高于其所在部门的平均薪水,
2 则将其薪水减50元,*/
3 -- Created on 2018/3/22 by XIONG
SQL> declare
2 -- Local variables here
3 myempno emp.empno%type;
4 empeg scott.emp%rowtype;
5 avgsal float;
6 saleg float;
7 i integer;
8 begin
9 -- Test statements here
10 myempno:= &no;
11 select * into empeg from emp where empno = myempno;
12 dbms_output.put_line(empeg.empno || ',' || empeg.ename || ',' || empeg.hiredate || ',' ||
13 empeg.sal || ',' || empeg.deptno);
14 select avg(sal)
15 into avgsal
16 from emp
17 group by deptno
18 having emp.deptno = empeg.deptno;
19 if empeg.sal > avgsal then
20 saleg := empeg.sal - 50;
21 update emp set emp.sal = saleg where emp.empno = myempno;
22 end if;
23 select * into empeg from emp where empno = myempno;
24 dbms_output.put_line(empeg.empno || ',' || empeg.ename || ',' || empeg.hiredate || ',' ||
25 empeg.sal || ',' || empeg.deptno);
26
27 end;
28 /
7839,KING,17-11月-81,5000,10
7839,KING,17-11月-81,4950,10
PL/SQL procedure successfully completed
6、创建一个存储过程,实现:通过输入员工编号查看员工姓名,工资,奖金;
1.1如果输入的编号不存在,进行异常处理;
1.2如果工资高于4000,进行异常提示处理;
1.3如果奖金没有或为0,进行异常提示处理;
SQL> create or replace procedure proc(i in int) as
2 -- Local variables here
3 ifexist number;
4 ename varchar2(10);
5 sal float;
6 comm float;
7 myempno number;
8 begin
9 -- Test statements here
10 myempno := i;
11 select count(*) into ifexist from emp where empno = myempno;
12 if ifexist = 0 then
13 dbms_output.put_line('编号不存在');
14 else
15 select ename, sal, comm
16 into ename, sal, comm
17 from emp
18 where empno = myempno;
19 if sal > 4000 then
20 dbms_output.put_line('工资高于4000');
21 end if;
22 if nvl(comm,0) = 0 then
23 dbms_output.put_line('该员工没有奖金');
24 end if;
25 end if;
26 end;
27 /
Procedure created
SQL> exec proc(1111);
编号不存在
PL/SQL procedure successfully completed
SQL> exec proc(7369);
该员工没有奖金
PL/SQL procedure successfully completed
SQL> exec proc(7839);
工资高于4000
该员工没有奖金
PL/SQL procedure successfully completed
SQL> exec proc(7654);
PL/SQL procedure successfully completed
SQL> select * from emp where empno in (1111,7369,7839,7654);
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
----- ---------- --------- ----- ----------- --------- --------- ------
7369 SMITH CLERK 7902 1980/12/17 800.00 20
7654 MARTIN SALESMAN 7698 1981/9/28 1250.00 1400.00 30
7839 KING PRESIDENT 1981/11/17 5000.00 10