--在调用PL/SQL的输出语句时必须打开输出开关,执行以下语句
set serveroutput on;
--1、在scott中创建存储过程xs_avg,该存储过程包括一个输入参数,用于获取部门号,一个输出参数用于返回指定部门的平均工资。并请给出此存储过程的一个调用实例。
--创建存储过程
create or replace procedure xs_avg(
t_deptno in dept.deptno%type, t_avg_sal out emp.sal%type)
as
begin
select avg(sal) into t_avg_sal from emp where deptno=t_deptno;
end;
--调用存储过程
declare
t_deptno dept.deptno%type:=&t_deptno;
t_avg_sal emp.sal%type;
begin
xs_avg(t_deptno,t_avg_sal);
dbms_output.put_line(t_avg_sal);
end;
运行结果:
--2、在emp表上创建一个触发器,当删除记录的时候,将被删除的数据、删除时间和用户保存到另一个表emp2中,请先自行设计并创建表emp2。
--复制表emp到emp2上
create table emp2 as select * from emp;
--清空表
delete from emp2;
--新增删除时间
alter table emp2 add del_time date;
--创建触发器
create or replace trigger del_info
before delete on emp for each row
declare
t_time date;
begin
--select sysdate into t_time from dual;
insert into emp2(empno,ename,job,mgr,hiredate,sal,comm,deptno,del_time) values
(:old.empno,:old.ename,
:old.job,:old.mgr,:old.hiredate,:old.sal,:old.comm,:old.deptno,sysdate);
--insert into emp2(del_time) values(to_date(t_time,'yy-MM-dd'));
end;
--添加一行数据用来删除,防止删除原表中数据难以恢复
insert into emp values(7000,'1','CLERK',7902,'17-12月-80',1000,500,10);
delete from emp where EMPNO=7000;
运行结果:
--3、在dept中创建触发器,当添加或修改部门记录时,同一个城市(loc)不允许超过2个部门。
/*注:在触发器的创建中,如果使用了for each row,那么在后面的PL/SQL语句中无法使用select语句,虽然会
编译通过,但是执行无效,所以如果需要用到查询,我们需要在定义触发器时不使用for each row*/
create or replace trigger in_up_dept
after insert or update on dept
declare
--用于储存当地部门的数量
dept_num number;
--统计当地的部门数
cursor deptno_count
is select count(deptno) from dept group by loc;
begin
open deptno_count;
fetch deptno_count into dept_num;
while deptno_count%found
loop
--判断,如果当地部门数大于2,那么撤回前面的操作
if dept_num>2 then
-- 抛出错误,撤回更改
raise_application_error(-20000,'over count!');
end if;
fetch deptno_count into dept_num;
end loop;
close deptno_count;
end;
--用来查看某部门的人数,便于迅速插入剩余的数据来检测触发器
select count(deptno),loc from dept group by loc;
--添加数据进行测试
insert into dept values(50,'赌馆','NEW YORK');
insert into dept values(60,'步行街','NEW YORK');
测试结果:
--4.在emp表上创建触发器,限制每个部门人数不能超过10人。
create or replace trigger limt_menber
before insert or update on emp
declare
--用来计数储存每个部门的员工号
menber_num number;
--定义游标用来遍历每个部门的员工数
cursor empno_num
is
select count(empno) from emp group by deptno;
begin
open empno_num;
--遍历统计部门的员工数
fetch empno_num into menber_num;
--如果empno_num能够读入有效的行数据,那么就执行
while empno_num%found
loop
--判断,如果当地部门数大于2,那么撤回前面的操作
if menber_num>=10 then
raise_application_error(-20000,'当地部门员工人数超过十人,无法更改或添加!');
end if;
fetch empno_num into menber_num;
end loop;
close empno_num;
end;
--添加人数进行测试
insert into emp values(7001,'2','CLERK',7902,'17-12月-80',1000,500,10);
insert into emp values(7002,'3','CLERK',7902,'17-12月-80',1000,500,10);
insert into emp values(7003,'4','CLERK',7902,'17-12月-80',1000,500,10);
insert into emp values(7004,'5','CLERK',7902,'17-12月-80',1000,500,10);
insert into emp values(7005,'6','CLERK',7902,'17-12月-80',1000,500,10);
insert into emp values(7006,'7','CLERK',7902,'17-12月-80',1000,500,10);
insert into emp values(7007,'8','CLERK',7902,'17-12月-80',1000,500,10);
insert into emp values(7008,'9','CLERK',7902,'17-12月-80',1000,500,10);
insert into emp values(7009,'10','CLERK',7902,'17-12月-80',1000,500,10);
运行结果:
--5.限制非上班时间(每天9:00以前、18:00以后)不允许更新salgrade数据。
--获取当前日期
select to_char(sysdate) from dual;
--获取当前时间(24小时制)
select to_char(sysdate,'hh24:mi:ss') from dual;
--获取当前的时钟数
select to_char(sysdate,'hh24') from dual;
--获取当前的分钟数
select to_char(sysdate,'mi') from dual;
--获取当前的秒钟数
select to_char(sysdate,'ss') from dual;
create or replace trigger ban_salgrade
before update or delete or insert on salgrade for each row
declare
--定义非法时间
morningTime varchar(10) := to_char('09:00:00');
nightTime varchar(10) := to_char('18:00:00');
--用于储存当前时间
nowTIme varchar(10);
begin
select to_char(sysdate,'hh24:mi:ss') into nowTime from dual;
if nowTime
RAISE_APPLICATION_ERROR(-20000, '在非上班期间不能更改数据');
end if;
end;
--测试用例
update salgrade set grade=10 where GRADE=1;
运行结果:
/*
--这段代码是用来测试字符串的比较是否能够成立的
declare
--定义非法时间
morningTime varchar(10) := to_char('09:00:00');
nightTime varchar(10) := to_char('18:00:00');
--用于储存当前时间
nowTIme varchar(10);
begin
select to_char(sysdate,'hh24:mi:ss') into nowTime from dual;
if nowTime>morningTime then
DBMS_OUTPUT.PUT_LINE('大于九点');
elsif nowTime DBMS_OUTPUT.PUT_LINE('小于六点'); end if; end;*/