开发子程序和包(修改后).ppt
ORACLE数据库查询和管理,第10章 开发子程序和包,程序块的语法结构:数据类型条件控制语句循环结构异常处理,内容回顾,%type%rowtype%record%table,DECLARE 定义部分BEGIN 执行部分EXCEPTION 异常处理部分END;,IF 条件表达式1 THEN语句段1ELSIF 条件表达式2 THEN语句段2ELSIF 条件表达式3 THEN语句段3.ELSIF 条件表达式n语句段nEND IF;,CASE 表达式WHEN 条件表达式结果1 THEN语句段1;WHEN 条件表达式结果2 THEN语句段2;.ELSE语句段n;END CASE;,LOOP语句段;EXIT WHEN 条件表达式END LOOP;,WHILE 条件表达式 LOOP语句段;END LOOP;,EXCEPTIONWHEN 异常错误名称1 THEN语句段1;WHEN异常错误名称2 THEN语句段2;.WHEN OTHERS THEN语句段3;,FOR 循环变量 in 初值表达式.终值表达式 LOOP语句段;END LOOP;,本章内容,过程函数程序包,本章目标,掌握过程的创建与使用掌握函数的创建与使用掌握包的创建与使用,1 子程序简介,子程序是指被命名的PL/SQL块,这种块可以带有参数,可以在不同应用中多次调用,类似于java中的函数 PL/SQL有两种类型的子程序:过程和函数 过程用于执行特定操作,不返回数据函数则用于返回特定数据,2 过程,过程一般用于执行一个指定的操作,可以将常用的特定操作封装成过程创建过程:,CREATE OR REPLACE PROCEDURE procedure_name(argument1 mode1 datatype1,argument2 mode2 datatype2,.)IS AS声明部分BEGIN执行部分EXCEPTION异常处理部分END;,创建过程:无参数创建一个无参过程,完成修改奖金的操作 执行过程的三种方式,create table tb_test(A varchar2(10),B varchar2(10);insert into tb_test values(aa,bb);insert into tb_test values(aa,cc);insert into tb_test values(bb,cc);insert into tb_test values(aa,bb);insert into tb_test values(aa,cc);insert into tb_test values(bb,cc);select*from tb_test,CREATE OR REPLACE PROCEDURE proc_del_dup_recASBEGINDELETE TB_TEST a WHERE a.rowid=(SELECT MAX(ROWID)FROM TB_TEST b WHERE a.a=b.a AND a.b=b.b);END;/,call proc_del_dup_rec();-exec proc_del_dup_rec;-begin proc_del_dup_rec;end;,创建过程:带有IN参数 当为过程定义参数时,如果不指定参数模式,则默认为输入参数根据输入的员工编号输出该员工的工资,创建过程时,无需为参数指定长度,因为过程中的参数长度最终是由传递给参数的外部数据长度来决定的,create or replace procedure pro_query_emp(v_no in emp.empno%type)asv_sal emp.sal%type;begin select sal into v_sal from emp where empno=v_no;dbms_output.put_line(该员工薪水为:|v_sal);exception when no_data_found then dbms_output.put_line(找不到该员工!);end;,声明输入参数 v_no,使用输入参数 v_no,begin pro_query_emp(7369);end;,创建过程:带有OUT参数 过程不仅可以用于执行特定操作,还可以用于输出数据在过程中输出数据时,需要使用OUT或IN OUT参数来完成 修改刚才的过程让员工工资作为输出参数,create or replace procedure pro_query_emp(v_no in emp.empno%type,out_sal out number)asbegin select sal into out_sal from emp where empno=v_no;exception when no_data_found then dbms_output.put_line(找不到该员工!);end;,声明输出参数 out_sal,给输出参数 out_sal赋值,调用带有OUT参数 的过程必须定义变量接收输出参数的数据,declarev_no emp.empno%type;v_sal emp.sal%type;begin v_no:=,定义输入和输出参数,创建过程:带有IN OUT参数 IN OUT参数也称为输入输出参数,当使用这种参数时,在调用过程之前需要通过变量给该种参数传递数据,调用结束后,Oracle会通过该变量将过程结果传递给应用,create or replace procedure pro_testinout(param_num in out number)asbegin select sal into param_num from emp where empno=param_num;end;,定义输入、输出参数,调用带 IN OUT参数的过程:,declareinout_num number;begin inout_num:=,输入时带入编号、输出时是工资的值。,过程调用时的多参数传递,使用过程时多参传递为形参传递变量和数据可以采用位置传递名称传递组合传递,create or replace procedure pro_add_dept(v_deptno number,v_dname varchar2,v_loc varchar2)asbegin insert into dept values(v_deptno,v_dname,v_loc);commit;end;,按位置传递按位置传递是指在调用时按参数的排列顺序依次写出实参的名称,将形参与实参关联起来进行传递在这种方法中,形参与实参的名称是相互独立、没有关系的,次序才重要,exec pro_add_dept(70,研发部,北京);,按照参数定义的顺序传入实参的值。,注意在oracle sql developer中报“无效SQL语句异常”。只能用call调用,而在命令窗口正常。,按名称传递按名称传递是指在调用时按照形参与实参的名称写出实参所对应的形参,将形参与实参关联起来进行传递在这种方法中,形参与实参的名称是相互独立、没有关系的,名称的对应关系很重要,但次序不重要名称传递在调用子程序时指定参数名,并使用关联符号“=”为其提供相应的数值或变量,call pro_add_emp(v_deptno=90,v_loc=南京,v_dname=软件部);,按照形参的名称赋值。,组合传递可以将按位置传递、按名称传递两种方法在同一调用中混合使用但前面的实参必须使用按位置传递方法,而后面其余的实参则可以使用按名称传递的方法,call pro_add_emp(90,v_loc=南京,v_dname=软件部);,第一个按形参位置传递,后面的按照形参的名称赋值。,3函数,函数用于返回特定数据,如果在应用程序中经常需要通过执行SQL语句来返回特定数据,则可以基于这些操作创建特定的函数,CREATE OR REPLACE FUNCTION function_name(argument1 model datatype1,argument2 mode2 datatype2,.)RETURN datatype IS|AS 声明部分 BEGIN 执行部分 EXCEPTION 异常处理部分 END;,创建函数,创建函数:当创建函数时,通过使用输入参数,可以将应用的数据传递到函数中,最终通过执行函数可以将结果返回到应用程序中 当定义参数时,如果不指定参数模式,则默认为输入参数,create or replace function fun_getrandom return numberasv_num number;-存储返回值begin v_num:=floor(dbms_random.value(1,10);-产生随机数 return v_num;-返回随机数end;,declarenum number;begin num:=fun_getrandom();dbms_output.put_line(num);end;,创建带输入参数的函数:通过输入员工编号获得员工所在的部门名称,create function getDept(eno number)return VARCHAR2asdeptName dept.dname%type;begin select dName into deptName from dept,emp where dept.deptno=emp.deptno and empno=eno;return deptname;end;,declare deptName VARCHAR2(30);begin deptName:=getDept(7654);dbms_output.put_line(deptname);end;,select getDept(7788)from dual,过程与函数的比较,过程与函数有许多相同的功能及特性都使用IN模式的参数传入数据、OUT模式的参数返回数据输入参数都可以接收默认值,都可以传值调用时的实参都可以使用位置表示法或名称表示法都有声明部分、执行部分和异常处理部分一般而言,如果需要返回多个值或不返回值,就使用过程如果只需要返回一个值,就使用函数虽然函数带OUT模式的参数也能返回多个值,但是一般都认为这种方法属于不好的编程习惯或风格过程一般用于执行一个指定的动作,函数一般用于计算和返回一个值,4 包,创建包包(Package)用于组合逻辑相关的PL/SQL类型、PL/SQL项和PL/SQL子程序通过使用PL/SQL包,不仅可以简化应用设计,提高应用性能,还可以实现信息隐藏、子程序重载等功能包由包规范和包体两部分组成当创建包时,需要首先创建包规范,然后再创建包体,创建包,创建包规范包规范是包与应用程序之间的接口,用于定义包的公用组件,包括常量、变量、游标、过程和函数在包规范中所定义的公用组件不仅可以在包内引用,而且还可以由其他的子程序引用创建包规范时需要注意的是:为了实现信息隐藏,不应该将所有组件全部放在包规范处定义,而应该只定义公用组件,CREATE OR REPLACE PACKAGE package_nameIS|ASpublic type and item declarationssubprogram specificationsEND package_name;,create or replace package dbutil_package ispi constant number(10,7):=3.1415926;function getarea(radius number)return number;procedure print_area;end dbutil_package;,创建包体为了实现包规范中所定义的公用过程和函数,必须创建包体 包体用于实现包规范所定义的过程和函数 在创建包时,为了实现信息隐藏,应该在包体内定义私有组件,CREATE OR REPLACE PACKAGE BODY package_nameIS|ASprivate type and item declarationssubprogram bodiesEND package_name;,create or replace package body dbutil_package asarea number(10);function getarea(radius number)return number isbegin area:=pi*radius*radius;return area;end;procedure print_area isbegin dbms_output.put_line(圆的面积是:|area);end;end dbutil_package;,注意:在oracle sql developer中运行编译后,会出现错误,导致不能正常执行。是因为其bug,将最后的分号丢掉了,再编辑一下,加上即可。,调用包的组件对于包的私有组件,只能在包内调用,并且可以直接调用 对于包的公用组件,既可以在包内调用,又可以在其他应用中调用 在调用同一包内其他组件,可直接调用,不需要加包名作为前缀 调用包的公用变量、过程、函数当在其他应用中调用包的公用变量时,必须在公用变量、过程、函数名前添加包名作为前缀,declarearea number(10,7);begin area:=dbutil_package.getarea(3);dbms_output.put_line(由function返回的面积:|area);dbutil_package.print_area;end;,查看子程序的源码通过查询数据字典USER_SOURCE,可显示当前用户的所有子程序及其源代码名称必须大写select text from user_source where name=DBUTIL_PACKAGE;删除子程序drop procedure proc_name;,子程序和包的管理,子程序源代码,查看包源代码通过查询数据字典USER_SOURCE,可以显示当前用户的包及其源代码select text from user_source where TYPE=PACKAGE and name=DBUTIL_PACKAGE;删除包如果只删除包体,则可以使用DROP PACKAGE BODY命令如果同时删除包规范和包体,则可以使用DROP PACKAGE命令,总结,创建过程创建函数创建包,CREATE OR REPLACE PROCEDURE procedure_name(argument1 mode1 datatype1,argument2 mode2 datatype2,.)IS AS声明部分BEGIN执行部分EXCEPTION异常处理部分END;,CREATE OR REPLACE FUNCTION function_name(argument1 model datatype1,argument2 mode2 datatype2,.)RETURN datatype IS|AS 声明部分 BEGIN 执行部分 EXCEPTION 异常处理部分END;,CREATE OR REPLACE PACKAGE package_nameIS|ASpublic type and item declarationssubprogram specificationsEND package_name;,CREATE OR REPLACE PACKAGE BODY package_nameIS|ASprivate type and item declarationssubprogram bodiesEND package_name;,THANK YOU,