Oracle 实验4(实验报告)-PL_SQL程序设计
ORACLE_PLSQL程序设计

ORACLE_PLSQL程序设计Oracle PL/SQL是一种强大的编程语言,用于开发Oracle数据库的存储过程、触发器、函数和包。
本篇文章将探讨Oracle PL/SQL程序设计的基本概念、语法和功能,以及一些最佳实践和编程技巧。
PL/SQL是Oracle数据库的内置编程语言,它结合了SQL语句和面向过程的语言特性,可以实现复杂的业务逻辑和数据处理。
PL/SQL程序是在数据库服务器上执行的,它可以访问和操作数据库中的数据,并返回结果。
PL/SQL程序由块组成,一个块是一组PL/SQL语句的逻辑单元。
块由关键字BEGIN和END包围,可以包含变量声明、控制结构、异常处理和SQL语句等。
PL/SQL变量是用来存储和操作数据的命名对象,它可以是标量类型(如整数、字符、日期等)、集合类型(如数组、表)或记录类型。
变量可以在块内部声明,并且可以被块内的其他语句引用。
PL/SQL控制结构用于根据条件执行特定的代码块。
常见的控制结构有IF-THEN、IF-THEN-ELSE、CASE等。
这些控制结构可以根据条件执行不同的代码块,增强了程序的灵活性和可读性。
异常处理是PL/SQL程序设计的重要部分。
当出现意外情况或错误时,异常处理机制可以捕获异常并采取相应的措施。
PL/SQL提供了TRY-CATCH结构来处理异常,可以在CATCH块中编写相应的异常处理代码。
PL/SQL还支持存储过程、触发器和函数等数据库对象的定义和使用。
存储过程是一种一次性地执行一系列操作的程序,触发器是在数据库中发生特定事件时自动执行的程序,函数是返回一个值的程序。
这些数据库对象可以帮助我们实现复杂的业务逻辑和数据操作。
在PL/SQL程序设计中,有一些最佳实践和编程技巧值得注意。
首先,要注意代码的可读性和可维护性,良好的命名约定、适当的缩进和注释可以提高代码的可读性。
其次,需要注意异常处理,正确处理和记录异常可以提高程序的稳定性和可靠性。
PLSQL程序设计

包括数值型(如NUMBER)、字符型(如VARCHAR2)、 日期型(如DATE)等。
01
集合数据类型
包括表、数组和集合,用于存储多个值。
02
03
自定义数据类型
使用COMMIT语句可以提交事务,将所有未提交的更改永久保存到数据库中。
感谢您的观看
THANKS
循环读取
使用循环结构(如WHILE循环)逐行读取游标中的数据。
异常处理
在读取游标数据时,应处理可能出现的异常,以确保程序的健壮 性。
游标的关闭
关闭游标
使用CLOSE语句关闭游标,释放与 游标相关的资源。
清理资源
关闭游标后,应释放所有与游标相关 的变量和资源,以避免内存泄漏。
06
PL/SQL事务处理
BEFORE触发器
在指定的事件(如INSERT、UPDATE或DELETE)之前执行的操作。
AFTER触发器
在指定的事件之后执行的操作。
INSTEAD OF触发器
用于视图,当对视图进行修改操作时,触发器中的操作替代了原本 的修改操作。
触发器的应用场景
数据完整性维护
触发器可用于确保数据的完整性,例如, 在更新员工工资时自动计算并更新员工
的总收入。
条件约束
触发器可用于实现复杂的业务规则, 例如,限制某些用户不能删除其他用
户的记录。
自动日志记录
触发器可以在数据修改时自动记录操 作日志,便于跟踪数据变更历史。
数据转换
触发器可以在数据修改时自动进行数 据转换或格式化,例如,将日期字段 自动转换为特定的格式。
05
PL SQL编程 Oracle数据库实验报告

PL/SQL编程【实验目的】1.熟悉PL/SQL的数据类型和书写规则2.熟悉控制结构和游标的使用3.编写和运行函数、过程和触发器【实验内容】编写脚本文件,调试运行脚本文件,并记录结果。
1.在SQL*Plus中编写一个PL/SQL块,功能用于打印学生信息在DECLARE部分完成:(1)建立学生信息记录类型stu_record_type,包括学号,姓名,性别,籍贯,学习成绩和活动成绩。
均为可变长字符类型(2)编写本地子过程:学生信息打印过程PrintStuRecord,把(1)中定义的记录类型作为参数(3)定义学生信息记录变量stu_record在BEGIN…END部分完成:(1)为stu_record变量的各个元素赋值如下:学号:‘2001001’姓名:’李新’性别:‘m’籍贯:‘黑龙江省哈尔滨市’学习成绩:‘Excellent’活动成绩:‘Good’(2)对该变量的调用打印过程,输出到屏幕2.建立对bookinfo表的DML触发器,一旦bookinfo表发生了任何变化,立即触发,对bookinfo表的数据进行统计,结果存储在数据统计表中(1)如果没有则建立bookinfo表,选择建立在scott用户下,表结构为(bookno varchar2(36) Primary key,bookname varchar2(40) not null,authorname varchar2(10) not null,publishtime date,bookprice float)(2)建立数据统计表major_stats,包含两个字段:书的总数和作者的总数(3)创建触发器UpdateMajorStats,完成在bookinfo表中插入、删除和修改记录之后,对bookinfo表进行统计,结果存储在(2)建立的major_stats表中(4)在bookinfo表中插入、删除和更新信息,再查看major_stats表中数据的变化【实验结论】编写脚本文件,调试运行脚本文件,并记录结果。
Oracle数据库实验-PLSQL游标、过程、函数、包的使用

Oracle数据库实验-PLSQL游标、过程、函数、包的使用Oracle数据库基础实验5 PL/SQL游标、过程、函数、包的使用【实验学时】2学时【实验目的】1.了解PL/SQL语言中显式游标和隐式游标的概念和属性。
2.了解显式游标和隐式游标的差异。
3.掌握PL/SQL中cursor for循环的使用方法。
4.学会在PL/SQL程序中使用游标来解决实际问题。
5.学会在PL/SQL程序中进行异常处理的方法。
6.练习在PL/SQL中自定义异常。
7.理解过程和函数的作用。
8.学会编写过程、函数、包,并加以调用。
【实验内容】1.用显式游标编写程序,程序的功能是:计算每一个部门的平均工资。
注意异常的处理(例如,分母为0的异常)。
已写入文件afiedt.buf1 declare2 cursor c_dept is select * from dept order by deptno;3 cursor c_emp(p_dept emp.deptno%type)is selectename,sal from emp where deptno=p_dept4 order by ename;5 r_dept dept%rowtype;6 v_ename emp.ename%type;7 v_salary emp.sal%type;8 v_tot_salary emp.sal%type;9 begin10 open c_dept;11 loop12 fetch c_dept into r_dept;13 exit when c_dept%notfound;14dbms_output.put_line('department:'||r_dept.deptno||'-'||r_de pt.dname);15 v_tot_salary:=0;16 open c_emp(r_dept.deptno);17 loop18 fetch c_emp into v_ename,v_salary;19 exit when c_emp%notfound;20dbms_output.put_line('name:'||v_ename||'salary:'||v_salary);21 v_tot_salary:=v_tot_salary+v_salary;22 end loop;23 close c_emp;24 dbms_output.put_line('total salary fordept:'||v_tot_salary);25 end loop;26 close c_dept;27* end;SQL> /PL/SQL 过程已成功完成。
Oracle SQL PLSQL实验

实验1SQL*Plus的使用和基本SELECT语句实验要求(1)掌握SQL*Plus的基本使用(2)掌握SELECT语句的简单用法。
实验条件自我实践实验时间大约60分钟1.练习1 FOLLOW ME●时间20分钟●实验步骤(1)观看第1章教学视频。
(2)实践视频中的实例。
2.练习2●时间40分钟●实验步骤(1)登录到SQL*Plus,初始用户名为:SCOTT,口令为TIGER。
(2)分别显示EMP、DETP、SALGRADE表结构,并察看表中的数据。
(3)创建一个查询显示每个雇员的姓名、工作、受雇日期及雇员编号,并且要将雇员编号作为第一列显示。
最后将该SQL语句保存成文件p1q1.sql,并执行该脚本文件。
(4)将脚本文件p1q1.sql调取到SQL缓冲区,并将列标题设置为Emp #,Employee,Job及Hire Date,将该SQL语句保存成文件p1q2.sql,最后返回查询结果。
思考练习题1.SQL*Plus命令是用于访问数据库的吗?2.下面的SELECT语句能成功执行吗?SQL>SELECT ename,job,sal Salary2FROM emp;3.下面的语句有3处错误,请纠正它们。
SQL>SELECT empno,ename2Salary x 12 ANNUAL SALARY3FROM emp;4.创建一个查询从EMP表中检索出不重复的工作名称。
5.用一个逗号和一个空格将姓名和工作连接后作为一个整体输出,显示的列标题为Employee and Title。
6.创建一个查询,用逗号将表中所有字段的信息连接作为一个整体输出,输出的列标题为THE_OUTPUT。
实验2使用WHERE和ORDER BY子句实验要求(1)掌握WHERE子句的用法。
(2)掌握ORDER BY子句的用法。
实验条件自我实践实验时间大约60分钟1.练习1FOLLOW ME●时间20分钟●实验步骤(1)观看第2章教学视频。
oracle综合性实验指导

湖南科技学院综合性实验指导书实验名称:PL/SQL编程实验项目性质:综合性所涉及课程:Oracle数据库计划学时:4一、实验目的(1)熟练掌握PL/SQL程序设计的基本知识。
(2)熟练掌握PL/SQL中控制结构的使用。
具体包括选择结构语句(IF语句和CASE语句),循环结构(四种循环结构)。
(3)熟练使用PL/SQL中系统函数。
(4)掌握PL/SQL中异常处理语句的使用(5)掌握PL/SQL中SELECT语句和DML语句的综合运用。
二、实验内容及步骤1.创建用户,指定密码、表空间。
用户名命名以本人姓名的缩写+‘_’+学号最后两位。
2.为该用户授予sysdba、connect、resource权限。
3.以本人的用户身份登录。
4.练习选择结构语句的使用方法。
1、条件语句IF 语法:IF <条件表达式> THEN<执行语句> …… <执行语句n>[ELSIF <条件表达式> THEN<执行语句> …… <执行语句n>……ELSE<执行语句>]END IF;2、分支语句CASE 语法:CASE <变量>WHEN <表达式1> THEN 值1WHEN <表达式2> THEN 值2……WHEN <表达式n> THEN 值nELSE 值n + 1END;例1:声明一个整型变量Num,使用IF语句判断Num变量是正数、负数或0。
SET ServerOutput ON;DECLARENum INTEGER := -11;BEGINIF Num < 0 THENdbms_output.put_line('负数');ELSIF Num >0 THENdbms_output.put_line('正数');ELSEdbms_output.put_line('0');END IF;END;例2、使用CASE语句根据给定的整数输出对应的星期值:SET ServerOutput ON;DECLAREvarDAY INTEGER := 3;Result V ARCHAR2(20);BEGINResult := CASE varDA YWHEN 1 THEN '星期一'WHEN 2 THEN '星期二'WHEN 3 THEN '星期三'WHEN 4 THEN '星期四'WHEN 5 THEN '星期五'WHEN 6 THEN '星期六'WHEN 7 THEN '星期七'ELSE '数据越界'END;dbms_output.put_line(Result);END;5.练习循环结构语句的使用方法。
《Oracle数据库》实验报告

实验二Oracle数据库开发环境下PL/SQL编程(2学时)【实验目的】(1)掌握PL/SQL 的基本使用方法。
(2)在SQL*PLUS环境下运行PL/SQL的简单程序。
(3)应用PL/SQL 解决实际问题【实验内容与步骤】一、实验内容:1、用PL/SQL实现:输入eno的值,显示emp表中对应记录的内容。
2、用PL/SQL完成:读入三个数,计算并输出它们的平均值及三个数的乘积。
3、对职工表emp中的雇员SCOTT提高奖金,若工种为MANAGER,则奖金提高其原来的20%;若工种为SALESMAN,则奖金提高其原来的15%;若工种为ANALYST,则奖金提高其原来的10%,其它都按原来的7%提高。
4、用PL/SQL块实现下列操作公司为每个职工增加奖金:若职工属于30号部门,则增加$150;若职工属于20号部门,则增加$250;若职工属于10号部门,则增加$350。
(提示:游标请自行阅读相关内容)DECLAREaddcomm m%type;CURSOR emp_cursor IS select deptno from emp;BEGINFOR emprec IN emp_cursor LOOPIF emprec.deptno=30 THEN addcomm:=150;ELSIF emprec.deptno=20 THEN addcomm:=250;ELSIF emprec.deptno=10 THEN addcomm:=350;END IF;Update empset comm=comm+ addcomm where deptno= emprec.deptno;END LOOP;COMMIT WORK;END;实验三PL/SQL触发器和存储过程(2学时)【实验目的】(1)了解触发器的类型。
(2)掌握PL/SQL触发器的使用方法。
(3)了解存储过程的使用方法。
(4)掌握存储过程的使用方法。
【实验内容】实验内容:1、编写一个数据库触发器,当任何时候某个部门从dept表中删除时,该触发器将从emp 表中删除该部门的所有雇员。
实验四 PLSQL高级编程

实验四PL/SQL高级编程开发语言及实现平台或实验环境:Oracle 11g实践目的(1) 掌握游标、存储过程、存储函数、包、触发器的基本作用。
(2) 掌握存储过程、存储函数、包、触发器的建立、修改、查看、删除操作。
实验要求(1) 记录执行命令和操作过程中遇到的问题及解决方法,注意从原理上解释原因。
(2) 掌握游标、存储过程、存储函数、包、触发器的命令。
实验内容1.创建存储过程(1) 将下列的未命名的PL/SQL,转换成存储过程,存储过程名自己设定,注意比较未命名的PL/SQL 与命名的PL/SQL 的差别,如没有where current of 是什么情况。
declarecursor emp_cursor is select * from emp where deptno=10 for update;beginfor emp_record in emp_cursor loopdbms_output.put_line(emp_record.sal);update emp set sal=sal*1.1 where current of emp_cursor;end loop;end;/执行sal=sal*1.1语句时,只对当前游标所指向的对象进行操作。
执行sal=sal*1.1语句时,对所有找到的游标对象进行操作。
(2)(3)任选一个(2) 创建存储过程“dept_count_pro_学号后四位”,实现显示scott方案中dept 表中各本门编号与名称,并显示对应部门的员工姓名和工资。
显示结果可如下图,也可自己设计:(3) 创建存储过程“num_pro_学号后四位”,通过传入参数传入3个数,完成3 个数的从小到大排序,通过 3 个传出参数保存排序后的 3 个数,并执行该存储过程,显示排序结果。
(4)通过user_source 数据字典中查看存储过程。
2.创建函数(1)(2)任选一个(1) 创建存储函数“emp_fun_学号后四位”,通过传入参数传入员工的编号,根据传入的员工编号,检查该员工是否存在。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
学期Oracle数据库应用技术实验报告选课序号:班级:学号:姓名:指导教师:***成绩:2017年月日目录1.实验目的 (1)2.实验内容 (1)2.1 触发器设计 (2)2.2 存储过程、自定义函数设计 (2)2.3 程序包设计 (3)3.实验步骤 (3)3.1 创建表空间RESTAURANT,创建用户DINER (3)3.2 创建餐饮系统数据库的所有表,并向各表插入演示数据 (4)3.3 完成【实验内容】中的触发器、存储过程、函数和程序包等功能设计,将程序脚本保存到文本文件Source.sql中 (7)4.实验总结 (13)PL/SQL程序设计1.实验目的◆掌握PL/SQL程序设计基本技巧,包括基本数据类型、表类型、数组类型、匿名程序块、控制语句、PL/SQL中使用SQL语句、游标、错误处理等。
◆熟悉和掌握PL/SQL中关于存储过程、函数、包和触发器程序设计技术。
2.实验内容实验平台:PL/SQL Developer或Oracle的其它客户端管理工具。
某餐饮系统数据库(加粗字段为主键,斜体字段为外键),请创建如下各数据表,并实现如下存储过程、函数、包和触发器等功能设计,将程序脚本保存到文本文件Source.sql中:(1)菜肴类别表MK(菜肴类别编号MKid,菜肴类别名称MkName),菜肴类别名称:鱼类、蔬菜类、凉菜类、肉类、主食类和酒水类等。
(2)菜单信息表MList(菜肴编号Mid,菜肴名称Mname,菜肴类别MKid,菜肴单价Mprice,菜肴成本单价Mcost,更新日期Mdate)。
(3)餐台类别表DK(餐台类别编号DKid,餐台类别名称DkName),餐台类别:包间和散台等。
(4)餐台信息表Dinfo (餐台编号Did,餐台名称Dname,餐台类别DKid,座位数Dseats,更新日期Ddate)。
(5)消费单主表C (消费单号Cid,餐台编号Did,消费开始时间StartTime,结账时间EndTime,消费金额合计Smoney,盈利金额合计SPsum),其中,消费金额合计=消费单明细表CList中该消费单号的所有消费记录的消费金额的合计,即SUM(消费金额)或SUM(菜肴单价×消费数量),盈利金额合计=消费单明细表CList中该消费单号的所有消费记录的盈利合计,即SUM((菜肴单价- 菜肴成本单价)×消费数量)。
(6)消费单明细表CList (消费单号Cid,序号Sid,菜肴编号Mid,菜肴名称Mname,消费数量Cqty,菜肴单价Mprice,菜肴成本单价Mcost,消费金额Cmoney) ,消费金额=消费数量×菜肴单价;消费数量为正数是正常点菜,消费数量为负数是退菜,消费数量为0是赠菜。
2.1 触发器设计2.1.1 为消费单明细表CList定义一个触发器,每插入(INSERT)一条消费单明细记录(消费单号,序号,菜肴编号,消费数量),自动根据菜肴编号从菜单信息表MList中读取菜肴名称Mname、菜肴单价Mprice、菜肴成本单价Mcost,然后计算其消费金额(=消费数量×菜肴单价)、以及消费单主表C的消费金额合计、盈利金额合计。
编写相应的插入语句(INSERT)和查询语句(SELECT)测试该触发器效果。
2.1.2 为消费单明细表CList定义一个触发器,每更新UPDATE一条消费单明细表记录,自动修改其消费金额、以及消费单主表C的消费金额合计、盈利金额合计。
编写相应的更新语句(UPDATE)和查询语句(SELECT)测试该触发器效果。
2.1.3 为消费单明细表CList定义一个触发器,每删除DELETE一条消费单明细表记录自动修改其消费单主表C的消费金额合计、盈利金额合计。
编写相应的删除语句(DELETE)和查询语句(SELECT)测试该触发器效果。
2.1.4 将【2.1.1】、【2.1.2】、【2.1.3】三个触发器禁用disable,重新编写一个触发器实现这三个触发器的全部功能。
编写相应的插入语句(INSERT)、更新语句(UPDATE)、删除语句(DELETE)和查询语句(SELECT)测试该触发器效果。
2.2 存储过程、自定义函数设计2.2.1设计一个自定义函数fGetDTSum,实现统计某年份给定餐台类别的成本金额合计的功能,输入参数是统计年份和餐台类别,返回数据是成本金额合计。
成本金额=消费数量×菜肴成本单价。
求年份的函数为EXTRACT(YEAR FROM 日期字段),本题:统计年份= EXTRACT(YEAR FROM EndTime),EndTime为结账时间字段。
2.2.2设计一个存储过程pGetKindSum,实现统计某年份给定菜肴类别的盈利金额合计的功能,输入参数是统计年份和菜肴类别,输出参数是盈利金额合计。
盈利金额=消费数量× (菜肴单价- 菜肴成本单价)。
2.2.3编写一段匿名PL/SQL程序块,调用函数fGetDTSum,输出2013年餐台类别名为“包间”的成本金额合计;调用存储过程pGetKindSum,输出2013年菜肴类别名为“鱼类”的盈利金额合计。
2.3 程序包设计2.3.1设计一个程序包,包名为pkSUM,包括并实现【2.2.1】和【2.2.2】的函数及存储过程功能,注意:先创建包头package,包头创建成功后,再创建包体package body。
2.3.2 设计一个匿名PL/SQL程序块,参照【2.2.3】调用【2.3.1】中程序包的函数和存储过程,输出2013年餐台类别名为“散台”的成本金额合计,输出2013年菜肴类别名为“蔬菜类”的盈利金额合计。
3.实验步骤(备注:如果用实验室微机,请从【3.2】开始做,登录用户DINER改为stu XX)3.1 创建表空间RESTAURANT,创建用户DINER3.1.2 用户SYSTEM登录Oracle3.1.3创建表空间RESTAURANT,大小10M。
CREATE TABLESPACE RESTAURANTDATAFILE'F:\RESTAURANT.ora'SIZE10MDEFAULT STORAGE(INITIAL10KNEXT50KMINEXTENTS1MAXEXTENTS99PCTINCREASE10)ONLINE;3.1.4 创建用户DINER,口令XXX,默认表空间RESTAURANT,给该用户授予角色权限CONNECT、RESOURCE。
CREATE USER DINER IDENTIFIED BY "wzl123" DEFAULT TABLESPACE RESTAURANT;GRANT CONNECT TO DINER;GRANT RESOURCE TO DINER;3.2 创建餐饮系统数据库的所有表,并向各表插入演示数据3.2.1启动PL/SQL Developer(或者启动SQL*PLUS、Enterprise Manager Console、浏览器模式的EM(企业管理器)等工具均可以),用户DINER登录Oracle。
3.2.2 创建实验内容中的餐饮系统数据库的所有表(菜肴类别表MK、菜单信息表MList、餐台类别表DK、餐台信息表Dinfo、消费单主表C、消费单明细表CList)。
create table MK(MKid number,MkName varchar2(64),constraint pk_MKid primary key(MKid));create table MList(Mid number,Mname varchar2(64),MKid number references MK(MKid),Mprice number(8,2),Mcost number(8,2),Mdate date,constraint pk_Mid primary key(Mid));create table DK(DKid number,DkName varchar2(64),constraint pk_DKid primary key(DKid));create table Dinfo(Did number,Dname varchar2(64),DKid number references DK(DKid),Dseats number,Ddate date,constraint pk_Did primary key(Did));create table C(Cid number,Did number references Dinfo(Did),StartTime date,EndTime date,Smoney number(8,2),SPsum number(8,2),constraint pk_Cid primary key(Cid));create table CList(Sid number,Cid number references C(Cid),Mid number references MList(Mid),Mname varchar2(64),Cqty number,Mprice number(8,2),Mcost number(8,2),Cmoney number(8,2),constraint pk_Sid primary key(Sid));3.2.3依次向菜肴类别表MK、菜单信息表MList、餐台类别表DK、餐台信息表Dinfo插入足够多的演示数据。
insert into MK values(1,'鱼类');insert into MK values(2,'蔬菜类');insert into MK values(3,'凉菜类');insert into MK values(4,'肉类');insert into MK values(5,'主食类');insert into MK values(6,'酒水');insert into MList values(1,'鲤鱼',1,50.00,30.00,sysdate); insert into MList values(2,'三文鱼',1,120.00,80.00,sysdate); insert into MList values(3,'白菜',2,15.00,5.00,sysdate); insert into MList values(4,'土豆',2,12.00,4.00,sysdate); insert into MList values(5,'油麦菜',2,12.00,5.00,sysdate); insert into MList values(6,'凉拌黄瓜',3,5.00,3.00,sysdate); insert into MList values(7,'鸡肉',4,30.00,10.00,sysdate); insert into MList values(8,'米饭',5,1.50,0.50,sysdate); insert into MList values(9,'二锅头',6,50.00,30.00,sysdate);insert into DK values(1,'包间');insert into DK values(2,'散台');insert into Dinfo values(1,'1号包间',1,20,sysdate);insert into Dinfo values(2,'2号包间',1,30,sysdate);insert into Dinfo values(3,'3号包间',1,50,sysdate);insert into Dinfo values(4,'1号散台',2,8,sysdate);insert into Dinfo values(5,'2号散台',2,8,sysdate);insert into Dinfo values(6,'3号散台',2,15,sysdate);insert into C values(1,2,sysdate,sysdate,275,150);insert into C values(2,2,sysdate,sysdate,155,80);insert into C values(3,1,sysdate,sysdate,566,302);insert into C values(4,2,sysdate,sysdate,89,53);insert into C values(5,1,sysdate,sysdate,798,435);insert into CList values(1,1,2,'三文鱼',1,120.00,80.00,120.00);insert into CList values(2,1,5,'油麦菜',1,12.00,5.00,12.00);insert into CList values(3,1,9,'二锅头',2,50.00,30.00,100.00);3.3 完成【实验内容】中的触发器、存储过程、函数和程序包等功能设计,将程序脚本保存到文本文件Source.sql中3.3.1 在PL/SQL Developer环境下,用户DINER登录Oracle3.3.2新建SQL窗口3.3.3 完成【2.1 触发器设计】(1)2.1.1CREATE OR REPLACE TRIGGER tri_CListBEFORE INSERT ON CList FOR EACH ROWDECLAREt_Smoney C.Smoney%type;t_SPsum C.SPsum%type;BEGIN--补全MlistSELECT Mname,Mprice,Mcost,:new.Cqty*MpriceINTO:new.Mname,:new.Mprice,:new.Mcost,:new.CmoneyFROM Mlist WHERE Mlist.Mid=:new.Mid;--计算Mlist的增加量SELECT NVL(SUM(Cqty*Mprice),0),NVL(SUM(Cqty*(Mprice-Mcost)),0)INTO v_Smoney,v_SPsum FROM Clist WHERE Clist.Cid=:new.Cid;--更新Cupdate C set Smoney=t_Smoney+:new.Cmoney,SPsum=t_SPsum+(:new.Cqty*(:new.Mprice-:new.Mcost)) where C.Cid=:new.Cid;END tri_CList;(2)2.1.2CREATE OR REPLACE TRIGGER tri_upCList BEFORE UPDATE ON CList FOR EACH ROWBEGINSELECT Mname,Mprice,Mcost INTO:new.Mname,:new.Mprice,:new.McostFROM Mlist WHERE Mlist.Mid=:new.Mid;:new.Cmoney:=NVL(:new.Cqty,:old.Cqty)*NVL(:new.Mprice,:old.Mprice);UPDATE C SET Smoney=Smoney-:old.Cmoney+:new.Cmoney,SPsum=SPsum-:old.Cqty*(:old.Mprice-:old.Mcost)+:new.Cqty*(:new.Mprice-:new.Mcost) WHERE C.Cid=:old.Cid;END tri_upCList;(3)2.1.3CREATE OR REPLACE TRIGGER tri_delCListBEFORE DELETE ON CList FOR EACH ROWBEGINUPDATE C SET C.Smoney=C.Smoney-:old.Cmoney,C.SPsum=C.SPsum-(:old.Cqty*(:old.Mprice-:old.Mcost))WHERE C.Cid=:old.Cid;END tri_delCList;(4)2.1.4CREATE OR REPLACE TRIGGER tri_allBEFORE INSERT OR UPDATE OR DELETEON CListFOR EACH ROWDECLAREt_Smoney C.Smoney%type;t_SPsum C.SPsum%type;BEGINIF INSERTING THENSelect Mname,Mprice,Mcost,:new.Cqty*Mpriceinto:new.Mname,:new.Mprice,:new.Mcost,:new.Cmoneyfrom Mlistwhere Mlist.Mid=:new.Mid;Select nvl(sum(Cqty*Mprice),0),nvl(sum(Cqty*(Mprice-Mcost)),0)into t_Smoney,t_SPsumfrom Clistwhere Clist.Cid=:new.Cid;update Cset Smoney=t_Smoney+:new.Cmoney,SPsum=t_SPsum+(:new.Cqty*(:new.Mprice-:new.Mcost)) where C.Cid=:new.Cid;ELSIF UPDATING THENselect Mname,Mprice,Mcostinto:new.Mname,:new.Mprice,:new.Mcostfrom Mlistwhere Mlist.Mid=:new.Mid;:new.Cmoney:=nvl(:new.Cqty,:old.Cqty)*nvl(:new.Mprice,:old.Mprice);Update C set Smoney=Smoney-:old.Cmoney+:new.Cmoney,SPsum=SPsum-:old.Cqty*(:old.Mprice-:old.Mcost)+:new.Cqty*(:new.Mprice-:new.Mcost) where C.Cid=:old.Cid;ELSEUPDATE C SETC.Smoney=C.Smoney-:old.Cmoney,C.SPsum=C.SPsum-(:old.Cqty*(:old.Mprice-:old.Mcost));END IF;END tri_all;3.3.4 完成【2.2 存储过程、自定义函数设计】(1)2.2.1CREATE OR REPLACE FUNCTION fGetDTSum(Cyear char,Ctable dk.dkname%type)RETURN C.spsum%TYPEAScons C.spsum%TYPE;BEGINselect nvl(sum(spsum),0)into cons from Cwhere did in(select did from dinfo where dkid in(select dkid from dk where dkname=Ctable))and(to_char(endtime,'YYYY')=Cyear);RETURN cons;EXCEPTIONWHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE('The data is invalid!');END fGetDTSum;(2)2.2.2CREATE OR REPLACE PROCEDURE pGetKindSum(Cyear char,Cname char,cons out clist.mcost%TYPE)ASBEGINselect nvl(sum(mprice-mcost),0)into cons from clist where mid in(select mid from mlist where mkid in(select mkid from mk where mkname=Cname))andcid in(select cid from C where to_char(endtime,'YYYY')=Cyear); EXCEPTIONWHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE('The data doesn’’t exists!'); END pGetKindSum;(3)2.2.3DECLAREcons1 C.spsum%TYPE;cons2 clist.mcost%TYPE;BEGINcons1:=fGetDTSum('2013','包间');pGetKindSum('2013','鱼类',cons2);DBMS_OUTPUT.PUT_LINE('cons1 '||cons1||'cons2 '||cons2||''); END;3.3.5完成【2.3 程序包设计】(1)2.3.1CREATE OR REPLACE PACKAGE pkSUMASFUNCTION fGetDTSum(Cyear char,Ctable dk.dkname%type)RETURN C.spsum%TYPE;PROCEDURE pGetKindSum(Cyear char,Cname char,cons out clist.mcost%TYPE);END pkSUM;CREATE OR REPLACE PACKAGE BODY pkSUMASCREATE OR REPLACE FUNCTION fGetDTSum(Cyear char,Ctable dk.dkname%type)RETURN C.spsum%TYPEAScons C.spsum%TYPE;BEGINselect nvl(sum(spsum),0)into cons from Cwhere did in(select did from dinfo where dkid in(select dkid from dk where dkname=Ctable))and(to_char(endtime,'YYYY')=Cyear);RETURN cons;EXCEPTIONWHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE('The data is invalid!');END fGetDTSum;CREATE OR REPLACE PROCEDURE pGetKindSum(Cyear char,Cname char,cons out clist.mcost%TYPE)ASBEGINselect nvl(sum(mprice-mcost),0)into cons from clistwhere mid in(select mid from mlist where mkid in(select mkid from mk where mkname=Cname))andcid in(select cid from C where to_char(endtime,'YYYY')=Cyear);EXCEPTIONWHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE('The data doesn’’t exists!');END pGetKindSum;END pkSUM;CREATE OR REPLACE PACKAGE BODY pkSUMASCREATE OR REPLACE FUNCTION fGetDTSum(Cyear char,Ctable dk.dkname%type)RETURN C.spsum%TYPEAScons C.spsum%TYPE;BEGINselect nvl(sum(spsum),0)into cons from Cwhere did in(select did from dinfo where dkid in(select dkid from dk where dkname=Ctable))and(to_char(endtime,'YYYY')=Cyear);RETURN cons;EXCEPTIONWHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE('The data is invalid!');END fGetDTSum;CREATE OR REPLACE PROCEDURE pGetKindSum(Cyear char,Cname char,cons out clist.mcost%TYPE)ASBEGINselect nvl(sum(mprice-mcost),0)into cons from clistwhere mid in(select mid from mlist where mkid in(select mkid from mk where mkname=Cname))andcid in(select cid from C where to_char(endtime,'YYYY')=Cyear);EXCEPTIONWHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE('The data doesn’’t exists!');END pGetKindSum;END pkSUM;(2)2.3.2DECLAREcons1 C.spsum%TYPE;cons2 clist.mcost%TYPE;BEGINcons1:=pkSUM.fGetDTSum1('2013','散台');pkSUM.pGetKindSum1('2013','蔬菜类',cons2);DBMS_OUTPUT.PUT_LINE('cons1:'||cons1||' cons2:'||cons2||'');END;4.实验总结这次实验让我学会了许多东西,比如PLSQL Developer的使用,高级PL/SQL 程序的编写,其中包括触发器,储存过程,自定义函数,匿名函数,程序包的设计与编写。