过程、函数和程序包

  • ORACLE

过程、函数和程序包

2年 ago mqzi

实验4 过程、函数和程序包

姓名:

郭佳堃  

学号:

1507112106

专业:

商务智能  

班级:

商务智能

同组人:

 

实验日期:

2017/07/04
         

【实验目的与要求】

  • 掌握过程的创建与调用

  • 掌握PL/SQL函数的编写与调用

  • 熟悉程序包的使用

【实验内容与步骤】

4.0.预备与说明

本实验中用到的表除作特殊说明外,均为scott模式下的表,如Emp表,请在实验时,连接到scott模式(以scott用户连接到数据库)。

在本实验中,会用到查询排序数据(比如:工资最高的5人个或工号最前面的5个人等),可用类似于如下的形式实现。

4.1.存储过程基础

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;

给出运行结果:

4.2.存储过程编写

在scott模式下,完成以下存储过程的编写,并进行测试,给出测试结果。

  1. 创建一个存储过程show_emp(),以员工号为参数,输出该员工的工资信息。

执行测试结果应如下:

(1)请给出程序源码:

create or replace procedure show_emp(v_empno int)

is

begin

dbmS_output.put_line(‘员工功耗为’|| v_empno);

end;

(2)请给出测试结果:

  1. 创建一个存储过程,以员工号为参数,修改该员工的工资:若该员工属于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) 完成后,请执行存储过程,并查询表中数据确认是否完成规定要求。

  1. 创建一个存储过程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)请给出测试结果:

4.3.函数使用基础

函数与存储过程的差别主要在于要设定返回值类型和调用(执行)方式不同。

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;

给出运行结果:

4.4.函数编写

  1. 编写函数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)请给出测试结果:

  1. 编写一个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;

请给出程序运行结果:

  1. 创建一个函数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;

请给出程序运行结果:

4.5.包的声明和使用

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;

给出运行结果:

4.6 作业与思考练习题

  1. 创建一个存储过程,以两个数为参数,输出工资排序在两个参数之间的员工信息(包括但不限于员工号、姓名、工资和部门号等)。

执行测试结果应如下:

(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)请给出测试结果:

  1. 编写一个存储过程checkSal( ),用以检查所指定雇员,传入员工工号作为参数,检查该员工的薪水是否在有效范围内。不同职位的薪水范围为:

Designation

Raise

Clerk 1500-2500
Salesman 2501-3500
Analyst 3501-4500
Others 4501 and above

如果薪水在此范围内,则显示消息”张三薪资是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;

请给出程序运行结果:

  1. 创建一个包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)请给出调用包中存储过程的执行结果:

Continue Reading

Previous PL/SQL编程之游标与异常处理

Next 触发器与作业

你可能感兴趣的:(过程、函数和程序包)