Oracle数据库基础学习DAY5

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

你可能感兴趣的:(Oracle)