Oracle——存储过程和函数练习题

Posted Xiu Yan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Oracle——存储过程和函数练习题相关的知识,希望对你有一定的参考价值。

文章目录


存储过程:

1、把数据表 fruits 中价格最低的两个水果的名称设置为“打折水果”

fruits 表结构可参考右侧链接:Oracle——PL/SQL 块结构练习题

set serveroutput on; -- 设置环境变量serveroutput为打开状态,使得pl/sql程序能够在SQL*plus中输出结果

-- 创建存储过程
create or replace procedure fruits_prc
as
begin
	update fruits set f_name = '打折水果' where f_id in(
		select f_id from (
			select * from fruits order by f_price asc
		)
		where rownum <= 2
	);
	commit;
end;
/				
		
exec fruits_prc --执行


查看结果:

select f_id, f_name from (
	select * from fruits order by f_price asc
)
where rownum <= 2;


2、创建一个存储过程用来统计表 sch 中的记录数和 sch 表中 id 的和

-- 创建表
create table sch(
	id number(8) primary key,
	name varchar2(20) not null,
	class varchar2(20) not null
);

-- 插入数据
insert into sch values(1, 'xiaoming', 'class1');
insert into sch values(2, 'xiaojun', 'class2');
--SQL%FOUND  判断SQL语句是否成功执行。当有作用行时则成功执行为true,否则为false。
create or replace procedure count_sch
as
	v_count number(5);
	v_sum number(5);
begin
	select count(*) into v_count from sch;
	select sum(id) into v_sum from sch;
	if sql%found then
		dbms_output.put_line('记录数为:'||v_count);
		dbms_output.put_line('id和为:'||v_sum);
	end if;
end;
/	

exec count_sch; -- 执行过程


3、指定学生姓名,查询该生的总学分,使用一个输入参数,一个输出参数

已知学生表(XS)存储信息:学号(Sno,int),姓名(Sname,char(10) ),总学分(Credit,int)。

-- 创建表
create table XS(
    xno number(10) primary key not null,
    sname varchar2(10),
    credit number(10)
    );
    
-- 插入数据 
insert into XS values(1, 'stu01', 200);
insert into XS values(2, 'stu02', 300);
insert into XS values(3, 'stu03', 120);

不使用输出参数,直接方式:

-- 创建存储过程
create or replace procedure student_credit
as
	v_sname XS.sname %TYPE := &v_sname;
	v_credit number(5);
begin 
	select credit into v_credit from XS where sname = v_sname;
	if sql%found then
		dbms_output.put_line('学生'|| v_sname ||'的总学分为:'||v_credit);
	end if;
end;
/

-- 创建存储过程
create or replace procedure student_credit(name in varchar2, total out number)
as
begin
	select sum(credit) into total from XS where sname = name;
end;
/

-- 调用结果
declare 
	stotal integer;
begin
	student_credit('stu02', stotal);
	dbms_output.put_line('输出结果:'||stotal);
end;
/


4、创建存储过程用来计算这个参数的平方或者平方根

创建一个存储过程,在其中定义一个IN OUT参数,该存储过程用来计算这个参数的平方或者平方根。

-- 创建存储过程
create or replace procedure pro_squre(num in out number, flag in boolean)
as
	i int := 2;
begin
	if flag then
		num := power(num, i);
	else
		num := sqrt(num);
	end if;
end;
/

-- 调用结果
declare 
	v_number number;
	v_temp number;
	v_flag boolean;
begin
	v_temp := &number;
	v_number := v_temp;
	v_flag := &flag;
	pro_squre(v_number, v_flag);
	if v_flag then	
		dbms_output.put_line(v_temp ||'的平方是:' ||v_number);
	else
		dbms_output.put_line(v_temp ||'的平方根是:' ||v_number);
	end if;
end;
/


函数:

1、创建一个通过雇员编号返回雇员名称的函数。

假设某公司需要创建一雇员表(employees),该表的已知需求如下:
雇员编号(EMPNO,4位数字),雇员名字(ENAME,最多10个字符),工种(JOB,最多10个字符),经理的编号(MGR,4位数字),聘用日期(HIREDATE),工资(SAL,保留2位小数),年终奖金比例(COMM,保留2位小数),所属部门编号( DEPTNO,3位数字)

create table employees(
    empno number(4)not null,
    ename varchar2(10),
    job varchar2(9),
    mgr number(4),
    hiredate date,
    sal number(7,2),
	comm number(7,2),
	deptno number(3));

修改表employees,删除字段年终奖金比例,添加字段奖金bonus,保留两位小数。

alter table employees drop column comm;
alter table employees add(bonus number(5, 2));

注意:本题需要创建用户并连接用户,在用户中进行表操作,因为超级用户 SYS 用户表中的列无法删除

执行结果:

--插入数据
insert into employees values(101, '雇员1', '工程师', '001', sysdate, 2500, 001, 500);
insert into employees values(102, '雇员2', '工程师', '001', sysdate, 2500, 001, 500);
insert into employees values(103, '雇员3', '工程师', '001', sysdate, 2500, 001, 500);

创建一个通过雇员编号返回雇员名称的函数GET_EMP_NAME。
要求进行异常处理,其中NO_DATA_FOUND没有符合条件记录,TO_MANY_ROWS返回多条符合条件记录。

-- 创建函数
create or replace function get_emp_name(p_empno number default 7788)
return  varchar2
as
	v_ename varchar2(10);
begin
	select ename into v_ename from employees where empno=p_empno;
	return v_ename;
	exception
		when no_data_found then
			dbms_output.put_line('没有该聘员编号!!');
			return null;
		when too_many_rows then
			dbms_output.put_line('重复该聘员编号!!');
			return null;
		when others then
			dbms_output.put_line('发生其他错误!');
			return (null);
end;
/

-- 调用函数
declare 
	v_ename employees.ename %TYPE;
begin
	v_ename:=get_emp_name(101);
	dbms_output.put_line('雇员的名字是:'||v_ename);
end;
/

执行结果:


2、创建一数据库函数,返回指定日期的收费总和

已知电信收费表call_fee,该表的已知需求如下:
包括交费日期(in_date,日期型)、话费(charge,数字型)和滞纳金(late_fee,数字型)等字段。不是每笔交费记录都包含有滞纳金,注意空值的处理。

-- 创建表
create table call_fee(
	in_date DATE,
	charge number(4),
	late_fee number(4)
);

-- 插入数据
insert into call_fee values(to_date('2020-10-10','yyyy-mm-dd'), 100, 200);
insert into call_fee values(to_date('2020-10-15','yyyy-mm-dd'), 200, 400);
-- 创建函数
create or replace function countfee(v_date date)
return number
as
	v_fee number;
begin
	select sum(charge)+sum(nvl(late_fee,0)) into v_fee from call_fee where in_date = v_date;
	return v_fee;
end;
/

--执行函数
declare 
	v_fee number;
	v_date date := to_date('2020-10-10','yyyy-mm-dd');
begin
	v_fee := countfee(v_date);
	dbms_output.put_line(v_date||'共花费:'||v_fee);
end;
/

以上是关于Oracle——存储过程和函数练习题的主要内容,如果未能解决你的问题,请参考以下文章

oracle pl/sql 存储过程

oracle习题-emp表查询练习

Oracle的sql语句上级练习和答案

Oracle的sql语句上机练习和答案

Oracle——触发器和游标练习题

Oracle——触发器和游标练习题