一、实验目的及要求
1.熟悉PL/SQL程序设计,练习使用PL/SQL的系统函数和异常处理。
2.理解存储过程、函数、触发器的概念、作用、建立和用法。
二、实验主要内容
编写PL/SQL程序,查询EMPLOYEES表员工工资,如果工资小于3000,则加200员工资,并提示信息“XX号员工工资已更新。”,如果工资大于3000,则提示信息“XX号员工工资为XXX,已达到规定标准。”练习使用异常处理,当除数为0时,输出错误信息。创建一存储过程,在存储过程中创建一个表用于存储临时数据,在创建该表之前需要进行判断,如果存在就删除该表的记录,不存在就创建该表。要求创建一存储过程,用于查询EMPLOYEES表中所有员工的信息,以及部门名称、工作名称。通过设置输入参数,使得存储过程能够灵活的选择要查询的部门名称以及工作名称,并输出到屏幕。创建函数,能够根据EMPLOYEE_ID,返回员工的LAST_NAME、EMAIL以及PHONE_NUMBER。创建一个触发器,保证新添加的员工工资不能超过已有员工的平均工资。创建一触发器,当删除EMPLOYEES表中记录时,显示删除的和剩余的记录数。完成实验报告。
三、实验仪器设备
在局域网环境下,有一台服务器和若干台客户机。服务器成功安装Oracle 11g数据库服务器(企业版),客户机成功安装Oracle 11g客户端软件,网络服务配置正确,数据库和客户端正常工作。
四、实验步骤
实验提交结合链接:https://blog.csdn.net/qq_41941875/article/details/83988366?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-0.pc_relevant_default&spm=1001.2101.3001.4242.1&utm_relevant_index=3 https://blog.csdn.net/qq_41941875/article/details/83988366?utm_medium=distribute.pc_relevant.none-task-blog-2~default~baidujs_title~default-0.pc_relevant_default&spm=1001.2101.3001.4242.1&utm_relevant_index=3
![](https://img-blog.csdnimg.cn/7a9e5342639f428b87bfe7ae4373cad7.png)
1. 新建数据库连接和数据表
(1)连接数据库 suke_conn
![](https://img-blog.csdnimg.cn/6b64e394f74647f7a17e5aeabd8682fa.png)
(2)创建四张表
![](https://img-blog.csdnimg.cn/234abc9f29494bd99b821e666b955929.png)
-- 创建数据表
CREATE TABLE dept (
deptno NUMBER(2) CONSTRAINT PK_DEPT PRIMARY KEY,
dname VARCHAR2(14) ,
loc VARCHAR2(13) ) ;
CREATE TABLE emp (
empno NUMBER(4) CONSTRAINT PK_EMP PRIMARY KEY,
ename VARCHAR2(10),
job VARCHAR2(9),
mgr NUMBER(4),
hiredate DATE,
sal NUMBER(7,2),
comm NUMBER(7,2),
deptno NUMBER(2) CONSTRAINT FK_DEPTNO REFERENCES DEPT );
CREATE TABLE bonus (
enamE VARCHAR2(10) ,
job VARCHAR2(9) ,
sal NUMBER,
comm NUMBER ) ;
CREATE TABLE salgrade (
grade NUMBER,
losal NUMBER,
hisal NUMBER );
(3)插入数据
![](https://img-blog.csdnimg.cn/1ba1e62c501046cab8fab1be606de7d4.png)
-- 插入测试数据 —— dept
INSERT INTO dept VALUES (10,'ACCOUNTING','NEW YORK');
INSERT INTO dept VALUES (20,'RESEARCH','DALLAS');
INSERT INTO dept VALUES (30,'SALES','CHICAGO');
INSERT INTO dept VALUES (40,'OPERATIONS','BOSTON');
-- 插入测试数据 —— emp
INSERT INTO emp VALUES (7369,'SMITH','CLERK',7902,to_date('17-12-1980','dd-mm-yyyy'),800,NULL,20);
INSERT INTO emp VALUES (7499,'ALLEN','SALESMAN',7698,to_date('20-2-1981','dd-mm-yyyy'),1600,300,30);
INSERT INTO emp VALUES (7521,'WARD','SALESMAN',7698,to_date('22-2-1981','dd-mm-yyyy'),1250,500,30);
INSERT INTO emp VALUES (7566,'JONES','MANAGER',7839,to_date('2-4-1981','dd-mm-yyyy'),2975,NULL,20);
INSERT INTO emp VALUES (7654,'MARTIN','SALESMAN',7698,to_date('28-9-1981','dd-mm-yyyy'),1250,1400,30);
INSERT INTO emp VALUES (7698,'BLAKE','MANAGER',7839,to_date('1-5-1981','dd-mm-yyyy'),2850,NULL,30);
INSERT INTO emp VALUES (7782,'CLARK','MANAGER',7839,to_date('9-6-1981','dd-mm-yyyy'),2450,NULL,10);
INSERT INTO emp VALUES (7788,'SCOTT','ANALYST',7566,to_date('19-04-1987','dd-mm-yyyy')-85,3000,NULL,20);
INSERT INTO emp VALUES (7839,'KING','PRESIDENT',NULL,to_date('17-11-1981','dd-mm-yyyy'),5000,NULL,10);
INSERT INTO emp VALUES (7844,'TURNER','SALESMAN',7698,to_date('8-9-1981','dd-mm-yyyy'),1500,0,30);
INSERT INTO emp VALUES (7876,'ADAMS','CLERK',7788,to_date('23-05-1987','dd-mm-yyyy')-51,1100,NULL,20);
INSERT INTO emp VALUES (7900,'JAMES','CLERK',7698,to_date('3-12-1981','dd-mm-yyyy'),950,NULL,30);
INSERT INTO emp VALUES (7902,'FORD','ANALYST',7566,to_date('3-12-1981','dd-mm-yyyy'),3000,NULL,20);
INSERT INTO emp VALUES (7934,'MILLER','CLERK',7782,to_date('23-1-1982','dd-mm-yyyy'),1300,NULL,10);
-- 插入测试数据 —— salgrade
INSERT INTO salgrade VALUES (1,700,1200);
INSERT INTO salgrade VALUES (2,1201,1400);
INSERT INTO salgrade VALUES (3,1401,2000);
INSERT INTO salgrade VALUES (4,2001,3000);
INSERT INTO salgrade VALUES (5,3001,9999);
2. 在SQL*Plus中使用PL/SQL块处理
EMP表中职工号7788的职工,如果工资小于3000那么把工资更改为3000
![](https://img-blog.csdnimg.cn/20931a6955284fd4826386b04549a8b9.png)
declare
x number(7,2);
begin
select sal into x from emp where empno=7788;
if(xEXECUT fire_emp(7654) PL/SQL procedure successfully completed.![在这里插入图片描述](https://img-blog.csdnimg.cn/20200811141111725.png)
存储过程删除了职工号7654的职工。
5. 带输入输出的存储过程
查询EMP中给定职工号的姓名、工资和佣金
![](https://img-blog.csdnimg.cn/99552468cf5046a6aa63316615da0ccd.png)
create or replace procedure query_emp
(v_emp_no in emp.empno%type,
v_emp_name out emp.ename%type,
v_emp_sal out emp.sal%type,
v_emp_comm out emp.comm%type)
is
begin
select ename,sal,comm
into v_emp_name,v_emp_sal,v_emp_comm
from emp where empno = v_emp_no;
end query_emp;
SQL> VARIABLE emp_name varchar2(15); SQL> VARIABLE emp_sal number; SQL> VARIABLE emp_comm number; SQL> EXECUTE query_emp(7654,:emp_name, :emp_sal, :emp_comm);
PL/SQL procedure successfully completed.
SQL> PRINT emp_name;
EMP_NAME
-------------------
MARTIN
6. 用Function查询出EMP中给定职工号的工资
create or replace function get_sal
(v_emp_no in emp.empno%type)
return number
is
v_emp_sal emp.sal%type :=0;
begin
select sal into v_emp_sal
from emp where empno = v_emp_no;
return (v_emp_sal);
end get_sal;
SQL>VARIABLE emp_sal number SQL>EXECUTE :emp_sal := get_sal(7654)
PL/SQL procedure successfully completed
.
SQL>PRINT emp_sal
EMP_SAL
-------------------
1250
7. 用异常处理完善程序
如例3中:解雇给定职工号的职工,并调用proc_execution
![](https://img-blog.csdnimg.cn/ea346ade54ce4d36b5ecfe53fcc5c9df.png)
create or replace procedure fire_emp
(v_emp_no in emp.empno%type)
is
begin
proc_execution;
delete from emp where empno = v_emp_no;
end fire_emp;
SQL>EXECUT fire_emp(7654)![在这里插入图片描述](https://img-blog.csdnimg.cn/20200811141204944.png)
如果职工号7654的职工不存在则出错。为了避免出错我们使用了EXCEPTION语句
![](https://img-blog.csdnimg.cn/e2d219f539e04deea0c916b43635c713.png)
create or replace procedure fire_emp
(v_emp_no in emp.empno%type)
is
begin
proc_execution;
delete from emp where empno = v_emp_no;
if sql%NOTFOUND then
raise_application_error(-20000, 'Employee does not exists.');
end if;
end fire_emp;
SQL>EXECUT fire_emp(7654)
就不会出错了。
8. 创建存储过程
实现功能为:删除scott.emp表中任意给定职工号的职工记录
![](https://img-blog.csdnimg.cn/7f798e793fda47d3842054b28ac78369.png)
create or replace procedure delete_emp
(id in dept.deptno%type)
is
begin
delete from dept where deptno = id;
end delete_emp;
9. 创建函数
实现功能为:在scott.emp表和scott.dept表中查询出任意给定职工号的职工姓名及职工所在部门的名称。
![](https://img-blog.csdnimg.cn/7de2184cc01f48cc8733522b726af66c.png)
create or replace function select_emp
(v_emp_no in emp.empno%type,
v_emp_name out emp.ename%type)
return dept.dname%type
as
v_dept_name dept.dname%type;
begin
select emp_ename,dept_dname
into v_emp_name,v_dept_name
from emp,dept
where emp.deptno=dept.deptno
and empno=v_emp_no;
return v_dept_name;
end select_emp;
10. 创建触发器
实现更新dept表中的deptno值,级联更新emp表中相应值
![](https://img-blog.csdnimg.cn/9fe8abc8b94145a2b5e8e048bf0c710b.png)
create or replace trigger update_dept_to_emp
after update on dept for each row
begin
if updating
then
update emp set deptno=:new.deptno
where deptno=old.deptno;
end if;
end update_dept_to_emp;
11. 对存储过程、函数及触发器实现查看、修改、删除等基本操作。
select object_name,status from user_objects where object_type='FUNCTION';
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200811141302468.png) ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200811141306596.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/2020081114131656.png) ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200811141324359.png) ![在这里插入图片描述](https://img-blog.csdnimg.cn/20200811141329828.png)
![在这里插入图片描述](https://img-blog.csdnimg.cn/20200811141333669.png)
|