




已阅读5页,还剩10页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
建立存储过程或函数存储过程或函数是存储ORACLE数据库中的PL/SQL程序,可由用户直接或间接调用。使用存储过程和函数主要优越性是:1、提高了效:在客户/服务器体系结构中,客户机应用向数据库服务器提出对SQL的需求。随着用户数量的增加,SQL 请求也就不断地增加,使网络很快就成为运行的瓶颈。使用存储过程可使运行性能得到显著的改进,因为对储过程的一个调用,即调用了在服务器中执行的多个SQL语句,从而减少了网络的拥挤。2、可重用性:一个PL/SQL程序只需编写一次,即可用于各种地方.3、可移植性:可在任何ORACLE数据库中使用存储过程,而不用考虑平台问题。4、可维护性:一个存储过程用于完成一个特定的任务,如数据库触发器等需要调用该过程的地方均调用同一个存储过程,这样可降低软件维护的成本。一、 存储过程1、 建立存储过程的语法。CREATE OR REPLACE PROCEDURE 程储过程名(参数1,参加n) IS局部变量声明部分BEGIN可执行部分例外处理部分END;说明:OR REPLACE 选项是当此存储过程存在时覆盖此程储过程。参数部分和过程定义的语法相同。例:定义一个存储过程用于删除students表中按学号指定的学生记录。CREATE OR REPLACE PROCEDURE DELE(STUID VARCHAR2) ISBEGINDELETE FROM STUDENTS WHERE STU_ID =STUID;END;2、 调用存储过程方法: EXECUTE 存储过程名(参数1,参数n);说明:参数1到参数n的类型与存储过程定义的类型必须一致,且参数的个数必须相同。例:调用DELE存储过程删除学号为1的学生记录。EXECUTE DELE(1);例:建立一个存储过程,在emp表中给按雇员号指定的人员增加工资,如果工资大于2000则增加50,否则如果工资大于1000则增加100,否则增加150。CREATE OR REPLACE PROCEDURE ADDSAL(EMPLOYNO EMP.EMPNO%TYPE) ISINCREMENT NUMBER;SALARY EMP.SAL%TYPE;BEGINSELECT SAL INTO SALARY FROM EMP WHERE EMPNO=EMPLOYNO;IF SALARY=2000 THENINCREMENT:=50;ELSIF SALARY=1000 THENINCREMENT:=100;ELSEINCREMENT:=150;END IF;UPDATE EMPSET SAL=SAL+INCREMENTWHERE EMPNO=EMPLOYNO;END;调用此存储过程,给雇员号为7369的记录增加相应的工资。Execute addsal(7369);二、 存储函数1、 语法CREATE OR REPLACE FUNCTION 函数名参数1,参数nRETURN 函数数据类型 IS 局部变量说明BEGIN可执行部分例外处理部分RETURN 函数的值END;说明:函数数据类型是函数返回值的数据类型;函数的值是返回给调用程序的数值。例:建立一个存储函数,统计指定部门的人数。CREATE OR REPLACE FUNCTION COUNTNUM (DEPNO NUMBER) RETURN NUMBER ISSUMA NUMBER;BEGINSELECT COUNT(*) INTO SUMA FROM EMP WHERE DEPTNO=DEPNORETURN SUMA;END;调用此函数时注意不能把函数单独的写成一行。可写在PL/SQL赋值语句的右端。或写在SELECT语句中等等。例:写一PL/SQL块统计10号部门和30号部门人数之和。Declare A number;BeginA:=countnum(10)+countnum(30);Dbms_output.put_line(a);End;例:建立一个存储过程,将STUDENTS表中按学号指定的学生记录移至HISTORY表中。并在history表中增加移入日期 (删除STUDENTS表中的记录,同时录入到HISTORY表中)。Create or replace procedure move( stuno varchar) isBegin/*将students中学号为stuno的记录插入到history表中*/Insert into history(stu_id,name,sex,ldate) select stu_id,name,sex ,sysdate from studentswhere stu_id=stuno;/*将students中学号为stuno的记录删除*/delete from studentswhere stu_id=stuno;end; 调用此存储过程,将学号为1的记录移入历史表execute move(1);例:编写一存储函数,将华氏温度转换成摄氏温度。Create or replace function degf_to_degC(deg_f in number)Return number isDeg_c number;BeginDeg_c:=(5.0/9.0)*(deg_f-32);Return deg_c;End;调用此函数,将PATIENT表中的body_temp以摄氏温度显示。Select patient_id, degf_to_degc(body_temp) from patient;在建立存储过程或存储函数时获取错误信息的方法。SHOW ERROR检索存储过程可以从数据字典视图user_source中查得。如查看当前用户模式下的存储过程和函数select name,type from user_source;查看一个具体的存储过程定义。例如查看move的定义可以用:select text from user_source where name=MOVE; *1、创建存储过程 create or replace procedure test(var_name_1 in type,var_name_2 out type) is-声明变量(变量名 变量类型)begin-存储过程的执行体end test;打印出输入的时间信息E.g:create or replace procedure test(workDate in Date) isbegindbms_output.putline('The input date is:'|to_date(workDate,'yyyy-mm-dd');end test;2、变量赋值变量名 := 值;E.g:create or replace procedure test(workDate in Date) isx number(4,2); begin x := 1; end test;3、判断语句:if 比较式 then begin end; end if;E.gcreate or replace procedure test(x in number) isbegin if x 0 then begin x := 0 - x; end; end if; if x = 0 then begin x: = 1; end; end if; end test;4、For 循环For . in . LOOP -执行语句 end LOOP; (1)循环遍历游标create or replace procedure test() isCursor cursor is select name from student; name varchar(20);beginfor name in cursor LOOP begin dbms_output.putline(name); end; end LOOP;end test;(2)循环遍历数组 create or replace procedure test(varArray in myPackage.TestArray) is-(输入参数varArray 是自定义的数组类型,定义方式见标题6)i number;begin i := 1; -存储过程数组是起始位置是从1开始的,与java、C、C+等语言不同。因为在Oracle中本是没有数组的概念的,数组其实就是一张-表(Table),每个数组元素就是表中的一个记录,所以遍历数组时就相当于从表中的第一条记录开始遍历for i in 1.varArray.count LOOP dbms_output.putline('The No.'| i | 'record in varArray is:'|varArray(i); end LOOP; end test;5、While 循环while 条件语句 LOOP beginend; end LOOP;E.gcreate or replace procedure test(i in number) isbeginwhile i 10 LOOP begin i:= i + 1;end; end LOOP; end test;6、数组首先明确一个概念:Oracle中本是没有数组的概念的,数组其实就是一张表(Table),每个数组元素就是表中的一个记录。使用数组时,用户可以使用Oracle已经定义好的数组类型,或可根据自己的需要定义数组类型。(1)使用Oracle自带的数组类型x array; -使用时需要进行初始化e.g:create or replace procedure test(y out array) is x array; beginx := new array();y := x;end test;(2)自定义的数组类型 (自定义数据类型时,建议通过创建Package的方式实现,以便于管理)E.g (自定义使用参见标题4.2) create or replace package myPackage is - Public type declarations type info is record( name varchar(20), y number); type TestArray is table of info index by binary_integer; -此处声明了一个TestArray的类型数据,其实其为一张存储Info数据类型的Table而已,及TestArray 就是一张表,有两个字段,一个是name,一个是y。需要注意的是此处使用了Index by binary_integer 编制该Table的索引项,也可以不写,直接写成:type TestArray is table of info,如果不写的话使用数组时就需要进行初始化:varArray myPackage.TestArray; varArray := new myPackage.TestArray();end TestArray;7.游标的使用 Oracle中Cursor是非常有用的,用于遍历临时表中的查询结果。其相关方法和属性也很多,现仅就常用的用法做一二介绍:(1)Cursor型游标(不能用于参数传递)create or replace procedure test() is cusor_1 Cursor is select std_name from student where .; -Cursor的使用方式1 cursor_2 Cursor;beginselect class_name into cursor_2 from class where .; -Cursor的使用方式2可使用For x in cursor LOOP . end LOOP; 来实现对Cursor的遍历end test;(2)SYS_REFCURSOR型游标,该游标是Oracle以预先定义的游标,可作出参数进行传递create or replace procedure test(rsCursor out SYS_REFCURSOR) iscursor SYS_REFCURSOR; name varhcar(20);beginOPEN cursor FOR select name from student where . -SYS_REFCURSOR只能通过OPEN方法来打开和赋值LOOP fetch cursor into name -SYS_REFCURSOR只能通过fetch into来打开和遍历 exit when cursor%NOTFOUND; -SYS_REFCURSOR中可使用三个状态属性: -%NOTFOUND(未找到记录信息) %FOUND(找到记录信息) -%ROWCOUNT(然后当前游标所指向的行位置) dbms_output.putline(name); end LOOP;rsCursor := cursor; end test;下面写一个简单的例子来对以上所说的存储过程的用法做一个应用:现假设存在两张表,一张是学生成绩表(studnet),字段为:stdId,math,article,language,music,sport,total,average,step 一张是学生课外成绩表(out_school),字段为:stdId,parctice,comment通过存储过程自动计算出每位学生的总成绩和平均成绩,同时,如果学生在课外课程中获得的评价为A,就在总成绩上加20分。create or replace procedure autocomputer(step in number) isrsCursor SYS_REFCURSOR;commentArray myPackage.myArray;math number;article number;language number;music number;sport number;total number;average number;stdId varchar(30);record myPackage.stdInfo;i number;begini := 1;get_comment(commentArray); -调用名为get_comment()的存储过程获取学生课外评分信息OPEN rsCursor for select stdId,math,article,language,music,sport from student t where t.step = step;LOOP fetch rsCursor into stdId,math,article,language,music,sport; exit when rsCursor%NOTFOUND;total := math + article + language + music + sport;for i in 1.commentArray.count LOOP record := commentArray(i); if stdId = record.stdId then begin if ment = 'A' then begin total := total + 20; go to next; -使用go to跳出for循环 end; end if; end; end if; end LOOP; average := total / 5; update student t set t.total=total and t.average = average where t.stdId = stdId; end LOOP;end;end autocomputer;-取得学生评论信息的存储过程create or replace procedure get_comment(commentArray out myPackage.myArray) isrs SYS_REFCURSOR; record myPackage.stdInfo; stdId varchar(30); comment varchar(1); i number;beginopen rs for select stdId,comment from out_schooli := 1;LOOP fetch rs into stdId,comment; exit when rs%NOTFOUND; record.stdId := stdId; ment := comment; recommentArray(i) := record; i:=i + 1; end LOOP;end get_comment;-定义数组类型myArray create or replace package myPackage is begintype stdInfo is record(stdId varchar(30),comment varchar(1);type myArray is table of stdInfo index by binary_integer;end myPackage;*oracle 存储过程的基本语法 及注意事项 oracle 存储过程的基本语法1.基本结构 CREATE OR REPLACE PROCEDURE 存储过程名字( 参数1 IN NUMBER, 参数2 IN NUMBER) IS变量1 INTEGER :=0;变量2 DATE;BEGINEND 存储过程名字2.SELECT INTO STATEMENT 将select查询的结果存入到变量中,可以同时将多个列存储多个变量中,必须有一条 记录,否则抛出异常(如果没有记录抛出NO_DATA_FOUND) 例子: BEGIN SELECT col1,col2 into 变量1,变量2 FROM typestruct where xxx; EXCEPTION WHEN NO_DATA_FOUND THEN xxxx; END; .3.IF 判断 IF V_TEST=1 THEN BEGIN do something END; END IF;4.while 循环 WHILE V_TEST=1 LOOP BEGIN XXXX END; END LOOP;5.变量赋值 V_TEST := 123;6.用for in 使用cursor . IS CURSOR cur IS SELECT * FROM xxx; BEGIN FOR cur_result in cur LOOP BEGIN V_SUM :=cur_result.列名1+cur_result.列名2 END; END LOOP; END;7.带参数的cursor CURSOR C_USER(C_ID NUMBER) IS SELECT NAME FROM USER WHERE TYPEID=C_ID; OPEN C_USER(变量值); LOOP FETCH C_USER INTO V_NAME; EXIT FETCH C_USER%NOTFOUND; do something END LOOP; CLOSE C_USER;8.用pl/sql developer debug 连接数据库后建立一个Test WINDOW 在窗口输入调用SP的代码,F9开始debug,CTRL+N单步调试关于oracle存储过程的若干问题备忘1.在oracle中,数据表别名不能加is,如:select a.appname from appinfo a;- 正确select a.appname from appinfo is a;- 错误 也许,是怕和oracle中的存储过程中的关键字is冲突的问题吧2.在存储过程中,select某一字段时,后面必须紧跟into,如果select整个记录,利用游标的话就另当别论了。 select af.keynode into kn from APPFOUNDATION af where af.appid=aid and af.foundationid=fid;- 有into,正确编译 select af.keynode from APPFOUNDATION af where af.appid=aid and af.foundationid=fid;- 没有into,编译报错,提示:Compilation Error: PLS-00428: an INTO clause is expected in this SELECT statement3.在利用o.语法时,必须先确保数据库中有该条记录,否则会报出no data found异常。 可以在该语法之前,先利用select count(*) from 查看数据库中是否存在该记录,如果存在,再利用o.4.在存储过程中,别名不能和字段名称相同,否则虽然编译可以通过,但在运行阶段会报错 select keynode
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025年成都数学压轴题库及答案
- 2025年传热学试卷及答案
- 车工实习总结
- 跨河大堤施工方案
- 秘密花园试题及答案
- 2025年音律的乐理题目及答案
- TB开拓者程序化交易编程课件
- STEM保护鸡蛋课件
- 爱国英文比赛题目及答案
- 小学综合病句题目及答案
- 遴选笔试真题及答案
- 2025年秋期新教材人音版三年级上册小学音乐教学计划+进度表
- 超级充电综合站及配套设施建设项目可行性研究报告
- 2025年湖北省武汉市中考语文真题(含答案)
- 中国心房颤动管理指南2025解读
- Unit1Weletotheunit课件译林版八年级英语上册
- 离职交接事项协议书范本
- 【高考真题】海南省2025年高考真题物理(含答案)
- 体育教师自我介绍课件
- 局工作秘密管理暂行办法
- 银行员工职业操守课件
评论
0/150
提交评论