星辰日月00

欲多则心散,心散则志衰,志衰则思不达也!

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

 子程序包括过程和函数。这里的所谓函数是指用户自定义函数。
从pl/sql程序设计的角度,也可以把子程序认为是pl/sql命名块,它存放在数据字典中,
可以在应用程序中进行多次调用。
 子程序存放在数据库服务器中,以编译方式运行,执行速度快。子程序一般是完成特定
功能的pl/sql程序块,具有一定的通用性,可以被不同应用程序多次调用,这样就简化了
应用程序的开发与维护,并能提高应用程序的性能。让用户程序通过调用子程序访问数据库,
而不是让用户程序直接访问数据库,这样做可以确保数据库的安全。

一、过程
 如果在用户应用中经常要执行某些操作,那么就可以将这些操作构造为一个过程。默认情况下,
用户定义的过程为该用户所拥有,数据库管理员可以把过程的使用权限授予其他用户。
1.定义过程
语法格式:
 

1 create [or replace] procedure procedure_name
2   [(argument_name [in | out | in out] argument_type [, ...])]
3  is | as
4  begin
5   procedure_body
6  end [procedure_name];

--argument_name指定参数的名字;argument_type指定参数的数据类型
--[in | out | in out]指定参数的模式,其中in表示参数是输入给过程的,out表示参数在过程中将被赋值
--in out表示该类型的参数既可以向过程体传递值,也可以在过程体中赋值,可以传给过程体的外部。
--关键字is和as可任选其一

 1 create or replace procedure display_teacher(
 2  v_no teacher.department_id%type
 3 )
 4 as
 5  v_wage teachers.wage%type;
 6  v_maxwage teachers.wage%type;
 7  v_minwage teachers.wage%type;
 8 begin
 9  select avg(wage) into v_wage
10   from teachers where department_id = v_no;
11  select max(wage) into v_wage
12   from teachers where department_id = v_no;
13  select min(wage) into v_wage
14   from teachers where department_id = v_no;
15  dbms_output.put_line('该系平均工资为:' || v_wage);
16  dbms_output.put_line('该系最高工资为:' || v_maxwage);
17  dbms_output.put_line('该系最低工资为:' || v_minwage);
18 exception
19  when no_data_found then
20   dbms_output.put_line('该系不存在。');
21 end display_teacher;

 

2.调用过程
语法格式:
 call | execute procedure_name(argument_list);
--关键字call和execute任选其一;procedure_name指定调用过程的名称;
--argument_list指定调用过程所需要传递的参数列表。
set serveroutput on
--使用CALL语句
call display_teacher(101);
--使用execute语句
execute display_teacher(101);
3.过程的管理
 过程的管理包括查看已建立过程的有关信息、查看过程中的错误、修改过程中的错误及删除过程等。
(1)查看已建立过程的有关信息

1  --通过数据字典中的user_objects视图,可以查看过程(对象)名object_name、过程建立时间created、
过程状态图status等信息。
2 select object_name, created, status 3 from user_objects 4 where object_name = 'display_teacher'; 5 --通过数据字典中的user_source视图,可以查看过程的源程序。 6 select text from user_source 7 where name = 'display_teacher';


(3)查看与修改过程中的错误
 在建立过程时,如果oracle系统报告错误,可以通过sql中的命令show errors查看错误信息,
通过sql中的命令edit修改错误。

 1 create or replace procedure display_teacher(
 2  v_no teacher.department_id%type
 3 )
 4 as
 5  v_wage teachers.wage%type;
 6  v_maxwage teachers.wage%type;
 7  v_minwage teachers.wage%type;
 8 begin
 9  select avg(wage) into v_wage
10   from teachers wheree department_id = v_no;
11  select max(wage) into v_wage
12   from teachers where department_id = v_no;
13  select min(wage) into v_wage
14   from teachers where department_id = v_no;
15  dbms_output.put_line('该系平均工资为:' || v_wage);
16  dbms_output.put_line('该系最高工资为:' || v_maxwage);
17  dbms_output.put_line('该系最低工资为:' || v_minwage);
18 exception
19  when no_data_found then
20   dbms_output.put_line('该系不存在。');
21 end display_teacher;

 

--警告:创建的过程带有编译错误。
show errors
******
edit
(3)删除过程
语法格式:
 drop procedure procedure_name;
drop procedure display_teacher;
4.参数及其传递
 建立过程时,传递的参数为可选项。如果省略参数选项,则过程为无参数过程——定义时
不指定参数,调用时也不需要参数;如果指定参数选项,则过程为有参数过程——定义时需
要指定参数名字、模式、数据类型,调用时需要给出对应参数。定义过程时指定的参数称为
形参,调用过程时给出的参数称为实参。
(1)无参数过程

1 create or replace procedure display_systime
2 as
3 begin
4  dbms_output.out_line('系统时间为:' || sysdate);
5 end display_system;
6 set serveroutput on
7 call display_systime();

 


(2)有参数过程
 带有参数的过程定义时需要指定参数名字、模式、数据类型,调用时需要给出对应参数。
--使用in参数

 1 create or replace procedure app_student(
 2  v_no in students.student_id%type,
 3  v_monitor_id in students.monitor_id%type,
 4  v_name in students.name%type,
 5  v_sex in students.sex%type,
 6  v_dob in students.dob%type,
 7  v_specialty in students.specialty%type
 8 )
 9 as
10 begin
11  insert into students values(
12   v_no, v_monitor_id, v_name, v_sex, v_dob, v_specialty
13  );
14 exception
15  when dup_val_on_index then
16   dbms_output.put_line('插入学生信息时,学生号不能重复');
17 end;
18 call app_student(101,102,'飞鸿','','03-4月-1987','自动化');
19 --使用in和out参数
20 create or replace procedure display_edited(
21  v_id in teachers.teacher_id%type,
22  v_name out teachers.name%type,
23  v_wage out teachers.wage%type
24 )
25 as
26  v_title teachers.title%type;
27 begin
28  select title into v_title
29    from teachers where teacher_id = v_id;
30  case
31   when v_title = '教授' then
32    update teachers
33      set wage = 1.1 * wage where teacher_id = v_id;
34   when v_title = '高工' or v_title = '副教授' then
35    update teachers
36      set wage = 1.1 * wage where teacher_id = v_id;
37   else
38    update teachers
39      set wage = wage + 100 where teacher_id = v_id;
40  end case;
41  select name, wage into v_name, v_wage
42   from teacher where teacher_id = v_id;
43 end display_edited;
44 variable v_name varchar2(10)
45 variable v_wage number
46 call display_edited(10101, :v_name, :v_wage);
47 --使用In out参数
48 create or replace procedure app_disp(
49  v_id in out departments.department_id%type,
50  v_name in out departments.department_name%type,
51  v_address in out departments.address%type
52 )  
53 as
54 begin
55  insert into departments
56   values(v_id, v_name, v_address);
57  v_id := v_id - 1;
58  select department_id, department_name, address
59   into v_id, v_name, v_address
60    from departments
61   where department_id = v_id;
62 exception
63  when dup_val_on_index then
64   dbms_output.put_line('插入系部信息时,系部号不能重复'。);
65  when no_data_found then
66   dbms_output.put_line('查询系部信息时,该系不存在。');
67 end;
68 variable v_id number
69 variable v_name varchar2(8)
70 variable v_address varchar2(40)
71 execute :v_id := 111
72 execute :v_name := '地理'
73 execute :v_address := 'X号教学楼';
74 call app_disp(:v_id, :v_name, :v_address);

 

(3)参数传递方式
 前面的例子,在调用带有参数的过程时,实参都是按照位置与形参进行对应传递的。
pl/sql同时也提供另外一种参数传递方式——按照参数名称传递。由于在传递多个参数时,
一些参数可以按照参数位置传递,另一些参数可以按照参数名称传递。因此,又有了混合传递参数的方式。
--参数传递使用名字传递方式
execute app_student(v_no => 10166, v_monitor_id => 10101,
 v_name => '张三', v_sex => '男', v_dob => '21-7月-1989', v_specialty => '计算机');
--参数传递使用混合传递方式
execute app_student(10177, 10101,
 v_name => '老四', v_sex => '男', v_dob => '22-5月-1989', v_specialty => '计算机');

 

过程和函数的区别:
过程:
    作为 PL/SQL 语句执行;
    在规范中不包含 RETURN 子句;
    不返回任何值(只有输入/输出参数,结果集);
    可以包含 RETURN 语句,但是与函数不同,它不能用于返回值。
函数:
    作为表达式的一部分调用;
    必须在规范中包含 RETURN 子句;
    必须返回单个值;
    必须包含至少一条 RETURN 语句。

posted on 2012-06-21 20:04  星辰日月00  阅读(237)  评论(0编辑  收藏  举报