2年 ago mqzi
姓名: |
郭佳堃 | 学号: |
1507112106 | |
专业: |
商务智能 | 班级: |
商务智能 | |
同组人: |
无 |
实验日期: |
2017/07/04 | |
【实验目的与要求】
掌握过程的创建与调用
掌握PL/SQL函数的编写与调用
熟悉程序包的使用
【实验内容与步骤】
本实验中用到的表除作特殊说明外,均为scott模式下的表,如Emp表,请在实验时,连接到scott模式(以scott用户连接到数据库)。
在本实验中,会用到查询排序数据(比如:工资最高的5人个或工号最前面的5个人等),可用类似于如下的形式实现。
1.最简单的存储过程编写与执行
以下是一个简单存储过程创建与执行的过程,请阅读并执行,熟悉存储过程的基本结构。
(1)创建存储过程
CREATE OR REPLACE PROCEDURE printMsg
is
BEGIN
dbms_output.put_line(‘第1个存储过程执行成功’);
END;
/
(2) 执行(调用)存储过程
在SQL plus的SQL>提示符下,使用Exec命令可执行存储过程,如下图:
请给出执行结果:
2.带参存储过程
存储过程的参数有in/out/in out等多种模式,其中用得最多也是默认的是in模式,可以省略。
(1)创创建简单带参存储过程
CREATE OR REPLACE PROCEDURE printMsgVal(v_msg varchar2)
is
BEGIN
dbms_output.put_line(v_msg);
END;
/
(2)执行存储过程
参于带参存储过程,在执行时,需根据参数类型使用变量或常量作为参数。在本过程中,参数可以是存放字符串的变量,或是常量,以下是一执行示例:
请自行设定参数值,执行以以上存储过程。
请给出执行结果:
3.存储过程参数模式
存储过程的参数模式包括in/out/in out三种:
其中in模式是将数据传入存储过程内部,只能用于赋值符号的右边;
out模式在使用是应用变量作为参数,其作用是将存储过程内部的数据通过存储过程带出存储过程之外,只能用于赋值符号的左边;out模式参数的调用,必须通过变量。
in out模式:也叫输入输出模式,能接收传入的实参值;在子程序内部可以修改; 可以输出
阅读以下程序,理解不同类型参数使用的不同,运行程序,给出运行结果。
(1) 参数传入与传出:in ,out 传入一个姓名
–创建存储过程
CREATE OR REPLACE PROCEDURE parTest( v_in in varchar2,
v_out out varchar2)
is
BEGIN
v_out:=v_in||’你好’;
dbms_output.put_line(‘传入参数值为:’||v_in );
END;
–在PL/SQL中调用存储过程
DECLARE
v_name varchar2(10);
BEGIN
parTest(‘scott’,v_name);
dbms_output.put_line(‘传出的参数值为:’||v_name);
END;
给出运行结果:
(3)一个返回多个值的存储过程。
以下程存过程可以将多个值带出,供程序的其他部分使用,请阅读并理解代码,给出测试结果。
–创建存储过程
create or replace procedure p_test(name out varchar2,age out number,sex out varchar2,sal out number)
is
begin
name:=’scott’;
age:=26;
sex:=’男’;
sal:=8000;
end;
–调用存储过程,注意其中值的传递形式
declare
v_name varchar2(20);
v_age number(10);
v_sex varchar2(5);
v_sal number(10);
begin
p_test(v_name,v_age,v_sex,v_sal);
dbms_output.put_line(v_name);
dbms_output.put_line(v_age);
dbms_output.put_line(v_sex);
dbms_output.put_line(v_sal);
end;
给出运行结果:
在scott模式下,完成以下存储过程的编写,并进行测试,给出测试结果。
创建一个存储过程show_emp(),以员工号为参数,输出该员工的工资信息。
执行测试结果应如下:
(1)请给出程序源码:
create or replace procedure show_emp(v_empno int)
is
begin
dbmS_output.put_line(‘员工功耗为’|| v_empno);
end;
(2)请给出测试结果:
创建一个存储过程,以员工号为参数,修改该员工的工资:若该员工属于10号部门,则工资增加150;若属于20号部门,则工资增加200;若属于30号部门,则工资增加250;若属于其他部门,则工资增加300.
要求:在存储过程中输出员工号、所在部门、原工资、更改后的工资值。
(1)请给出程序源码:
Create Or Replace Procedure Hah(V_No Number)
is
V_Temp Emp.Deptno%Type;
V_Temp2 Emp.Sal%Type;
V_Temp3 Emp.Sal%Type;
Begin
Select Deptno Into V_Temp from emp Where Empno=V_No;
Select Sal Into V_Temp2 from emp Where Empno=V_No;
If V_Temp=10 Then
Update Emp Set Sal=Sal+150 Where Deptno=V_Temp;
Elsif V_Temp=20 Then
Update Emp Set Sal=Sal+200 Where Deptno=V_Temp;
Elsif V_Temp=30 Then
Update Emp Set Sal=Sal+250 Where Deptno=V_Temp;
Else
Update Emp Set Sal=Sal+300 Where Deptno=V_Temp;
end if;
Select Sal Into V_Temp3 from emp Where Empno=V_No;
Dbms_Output.Put_Line(‘员工号:’||V_No);
Dbms_Output.Put_Line(‘所在部门:’||V_Temp);
Dbms_Output.Put_Line(‘原工资:’||V_Temp2);
Dbms_Output.Put_Line(‘现工资:’||V_Temp3);
End;
(2) 完成后,请执行存储过程,并查询表中数据确认是否完成规定要求。
创建一个存储过程maxSal( ),以一个整数为参数,输出工资最高的前N个(如:前3个,其中N为参数值)员工的信息。
提示:多行数据的输出可考虑使用游标操作。
执行测试结果应如下:
(1)请给出程序源码:
Create Or Replace Procedure Maxsal(V_N Int)
Is
Cursor Xx Is Select * From Emp Order By Sal Desc;
V_Temp Number:=0;
Begin
For Hh In Xx Loop
If V_Temp Dbms_Output.Put_Line(Hh.Empno||’ ‘|| hh.ename||’ ‘||hh.sal); Else Exit; End If; V_Temp:=V_Temp+1; End Loop; End; (2)请给出测试结果: 函数与存储过程的差别主要在于要设定返回值类型和调用(执行)方式不同。 1.最简单的函数: 以下通过一个简单函数使用示例说明函数的创建和调用。 (1)创建函数 CREATE FUNCTION getName(name in varchar2) RETURN varchar2 is BEGIN return name; END; (2)调用函数 函数的调用可以使用select 语句,或者将函数用于PL/SQL程序块中调用。 a.使用查询语句调用 以下是使用查询语句调用函数的示例: 请自行指定参数,按该方式调用函数getName()。 给出执行结果: b.在程序中调用 以下是在程序段是调用函数的示例,请执行并给出结果。 DECLARE v_name varchar2(10); BEGIN v_name:=getName(‘scott’); dbms_output.put_line(‘函数返回值为:’||v_name); END; 给出运行结果: 2.稍微复杂的函数 以下函数实现的是根据传入的工资值,判断工资水平,请理解并执行程序。 –编写函数 CREATE OR REPLACE FUNCTION salarylevel(salary number) RETURN varchar2 is BEGIN IF alary < 1000 THEN RETURN ‘工资太低了,要加油了’; ELSIF salary <3000 THEN return ‘还可以,但是也要努力啊’; ELSIF salary <5000 THEN return ‘这个还可以’; ELSE return ‘你的工资现在来说,是比较高了’; END IF; END; –调用函数 DECLARE v_salarylevel varchar2(50); BEGIN v_salarylevel := salarylevel(1000); dbms_output.put_line(v_salarylevel); END; 给出运行结果: 编写函数getY(v_x number ),实现以下功能 (1)请给出程序源码: Create Or Replace Function Gety(V_X Number) Return Number Is Begin If V_X<1 Then Return V_X; Elsif V_X>=1 And V_X<6 Then Return 6*V_X-1; Elsif V_X>=6 Then Return 3*Power(V_X,2)-18; End If; End; (2)请给出测试结果: 编写一个PL/SQL函数count_by_Salary,接受传入参数Salary_min和Salary_max,据此统计并返回薪水值在Salary_min和Salary_max之间的员工人数。 请给出程序源码: create or replace function count_by_Salary(Salary_min number,Salary_max number) return number is v_temp number:=0; cursor xx is select * from emp; begin for hh in xx loop if hh.sal>Salary_min and hh.sal v_temp:=v_temp+1; end if; end loop; return v_temp; end; 请给出程序运行结果: 创建一个函数getAveSal(),以员工号为参数,返回该员工所在部门的平均工资。 请给出程序源码: create or replace function getAveSal(v_empno number) return number is v_temp number:=0; begin select avg(sal) into v_temp from emp where deptno in(select deptno from emp where empno=7369); return v_temp; end; 请给出程序运行结果: Oracle中包的使用包括声明和实现,包的实现主要包括包头和包体,其中包头主要用于定义接口,包体主要用以实现包体中声明的存储过程、函数等。 阅读以下程序,理解包的声明和使用。 ———–包的声明和使用1————————- –创建测试用表 CREATE TABLE Exam_Emps( id number(5) primary key, name varchar2(30), commission_pct number(3,2 ) ); –添加测试数据 insert into Exam_Emps values (1,’张司’,0.13); insert into Exam_Emps values (2,’关于’,0.23); insert into Exam_Emps values (3,’李世民’,0.33); insert into Exam_Emps values (4,’唐高’,0.43); commit; –检查是否有测试数据 select * from Exam_Emps; –创建包头 CREATE OR REPLACE PACKAGE comm_package IS g_comm NUMBER := 0.10; PROCEDURE reset_comm (p_comm IN NUMBER); END comm_package; / –创建包体 CREATE OR REPLACE PACKAGE BODY comm_package IS ————-在包体中定义的局部函数————– /* 如果输入的参数p_comm大于Exam_Emps表中最大的commission_pct 字段,则函数返回FALSE,否则函数返回TRUE */ FUNCTION validate_comm (p_comm IN NUMBER) RETURN BOOLEAN IS v_max_comm NUMBER; BEGIN SELECT MAX(commission_pct) INTO v_max_comm FROM Exam_Emps; IF p_comm > v_max_comm THEN RETURN FALSE ; ELSE RETURN TRUE ; END IF; END validate_comm; ———在包体中定义的局部函数:结束———— ————完成在包体中声明的过程————– PROCEDURE reset_comm (p_comm IN NUMBER) IS BEGIN IF validate_comm(p_comm) THEN g_comm:=p_comm; ELSE RAISE_APPLICATION_ERROR(-20210, ‘不合理的表达式’); END IF; END reset_comm; ———-完成在包体中声明的过程:结束———— END comm_package; –测试包:使用sql plus命令 EXEC comm_package.reset_comm(1); EXEC comm_package.reset_comm(.33); 给出运行结果: –测试包:在程序行中使用 begin comm_package.reset_comm(0.15); dbms_output.put_line(‘g_comm = ‘ || comm_package.g_comm ); end; / 给出运行结果: ———–包的声明和使用2————————- create or replace package tax_pkg as function tax(v_value in number) return number; end tax_pkg; / create or replace package body tax_pkg as ————-包体中的函数执行部分————— function tax(v_value in number) return number is begin if v_value < 1000 then return (v_value * 0); elsif v_value < 5000 then return (v_value * 0.10); elsif v_value <10000 then return (v_value * 0.15); else return (v_value * 0.20); end if; end tax; ————-包体中的函数:结束—————– end tax_pkg; / — 测试包中定义的函数 select salary,tax_pkg.tax(salary) from Exam_Emp; 给出运行结果: 创建一个存储过程,以两个数为参数,输出工资排序在两个参数之间的员工信息(包括但不限于员工号、姓名、工资和部门号等)。 执行测试结果应如下: (1)请给出程序源码: create or replace procedure select_emp(Salary_min number,Salary_max number) is v_temp number:=0; cursor xx is select * from emp; begin for hh in xx loop if hh.sal>Salary_min and hh.sal dbms_output.put_line(hh.empno||’ ‘||hh.ename||’ ‘||hh.sal); end if; end loop; end; (2)请给出测试结果: 编写一个存储过程checkSal( ),用以检查所指定雇员,传入员工工号作为参数,检查该员工的薪水是否在有效范围内。不同职位的薪水范围为: Designation Raise 如果薪水在此范围内,则显示消息”张三薪资是XXX,Salary is OK”,否则,更新薪水为该范围内的最低值。(注:其中张三为员工姓名,XXX为员工薪资,实现时请用具体值代替)。 请给出程序源码: Create Or Replace Procedure Checksal(V_Empno Number) Is V_Temp Number; V_Temp2 Varchar2(255); V_Name Varchar2(255); Begin Select Sal Into V_Temp From Emp Where Empno=V_Empno; Select Job Into V_Temp2 From Emp Where Empno=V_Empno; Select Ename Into V_Name From Emp Where Empno=V_Empno; If V_Temp2=’CLERK’ And V_Temp>1500 And V_Temp<2500 Then Dbms_Output.Put_Line(V_Name||’薪资是:’||V_Temp||’Salary is OK’); Elsif V_Temp2=’CLERK’ Then Update Emp Set Sal=1500 Where Empno=V_Empno; Elsif V_Temp2=’SALEMAN’ And V_Temp>2501 And V_Temp<3500 Then Dbms_Output.Put_Line(V_Name||’薪资是:’||V_Temp||’Salary is OK’); Elsif V_Temp2=’SALEMAN’ Then Update Emp Set Sal=2500 Where Empno=V_Empno; Elsif V_Temp2=’ANALYST’ And V_Temp>3501 And V_Temp<4501 Then Dbms_Output.Put_Line(V_Name||’薪资是:’||V_Temp||’Salary is OK’); Elsif V_Temp2=’ANALYST’ Then Update Emp Set Sal=3500 Where Empno=V_Empno; End If; End; 请给出程序运行结果: 创建一个包pkg_emp,包中包含一个函数getMaxSal()和一个存储过程getEmp()。函数以部门号为参数,返回该部门员工的最高工资;过程以部门号为参数,输出该部门中工资最高的员工名、员工号。 要求完成后,可以以如下方式调用包: (1)调用包中函数: (2)调用包中存储过程 (1)请给出程序源码: Create Or Replace Package Pkg_Emp Is Procedure Getemp(V_Deptno Number); Function Getmaxsal(V_Deptno Number) Return Number; End; Create Or Replace Package Body Pkg_Emp Is Procedure Getemp(V_Deptno Number) Is Cursor Xx Is Select * From Emp Where Sal In (Select Max(Sal) From Emp Where Deptno=V_Deptno); Begin For Hh In Xx Loop Dbms_Output.Put_Line(Hh.Empno||’ ‘||Hh.Ename); End Loop; End; Function Getmaxsal(V_Deptno Number) Return Number Is V_Sal Number; Begin Select Max(Sal) Into V_Sal From Emp Where Deptno=V_Deptno; Return V_Sal; End; End; (2)请给调用包中函数的执行结果: (3)请给出调用包中存储过程的执行结果: Previous PL/SQL编程之游标与异常处理 Next 触发器与作业4.3.函数使用基础
4.4.函数编写
4.5.包的声明和使用
4.6 作业与思考练习题
Clerk
1500-2500
Salesman
2501-3500
Analyst
3501-4500
Others
4501 and above
Continue Reading