1、INTOTEMP(n)VALUES(0); 4. ENDINSERT_TEMP;PROCEDURE INSERT_TEMP ISBEGIN INSER INTO TEMP (n) VALUES (0);END INSERT_TEMP; 常见的过程样式是将IS、BEGIN、EXCEPTION和END对齐。这些关键字作用域内的全部代码都要进行缩进。PRINT_TEMP2. ISv_averageNUMBER;4. v_sum5. BEGIN6. SELECTAVG(N),SUM(N)v_average,v_sumFROMTEMP;7. dbms_output.put_line(Average:|)
2、;8. dbms_output.put_line(Sum:v_sum);9. ENDPRINT_TEMP;PROCEDURE PRINT_TEMP IS v_average NUMBER; v_sum NUMBER; SELECT AVG(N), SUM(N) INTO v_average,v_sum FROM TEMP; dbms_output.put_line(Average: | v_average ); dbms_output.put_line(Sum: | v_sum);END PRINT_TEMP; 单独的过程常会开发成为一个新包或者一个已有的包合并。将INSERT_TEMP合并到
3、一个包中,仅需要进行下面简单的编辑工作:1. 首先在ORACLE建立PACKAGE 1. CREATEORREPLACEPACKAGETEMP_OP2. PROCEDURE3. ENDTEMP_OP;CREATE OR REPLACE PACKAGE TEMP_OP IS PROCEDURE INSERT_TEMP;END TEMP_OP;2. 建立PACKAGE BODY BODYBEGININSERTtemp(n)5. END6. ENDCREATE OR REPLACE PACKAGE BODY TEMP_OP IS PROCEDURE INSERT_TEMP IS BEGIN INSE
4、RT INTO temp(n) VALUES (0); END INSERT_TEMP;二、函数(FUNCTION) 包通常扮演API的角色,隐藏对象,提供对象上的操作。而函数常扮演对象状态信息的选择器。设想一个要计算对象的某个属性值的函数。函数不是动作者,而是状态的计算值。所以应该用名词对函数进行命名。FUNCTION student_status RETURN VARCHAR2 IS BEGIN 子程序体Program body RETURN expression;EXCEPTION 异常处理程序,其中应该包括一条RETURN语句 student_status;参数是可选的,但是RETUR
5、N 语句却是必须具备的,FUNCTION语句必须包括一个RETURN 和类型。说明:1.声明部分 声明变量,需要返回的变量也是在这里声明的。函数必须具有返回值。如果函数的返回值是一个NUMBER,则该NUMBER变量就在这里声明。该变量应该出现在RETURN语句中。2.子程序体 支持循环、if-then-else结构、case语句和declare-block 结构。程序体必须包括RETURN语句。3.异常处理程序 可选的,可以编写用于特定类型错误的异常处理程序或者是通用的异常处理程序,确定异常处理程序中包含了RETURN语句。tomorrowRETURNDATEnext_dayDATE;4.
6、BEGIN:=SYSDATE+1;next_day;7. ENDtomorrow;CREATE OR REPLACE FUNCTION tomorrow RETURN DATE next_day DATE; next_day := SYSDATE +1 ; RETURN next_day;END tomorrow;不声明变量,可以直接简写为:CREATE OR REPLACE FUNCTION tomorrow RETURN DATE IS RETURN SYSDATE +1 ;如果函数没有参数,则不要在函数定义时使用空括号。这规则同样适用于过程。使用函数:sample today1;6. d
7、bms_output.put_line(tomorrow-1);sample;CREATE OR REPLACE sample today DATE; today := tomorrow 1;dbms_output.put_line(tomorrow - 1);END sample;三、包(PACKAGE) 利用包提供这样一套机制:将较小的程序单元在逻辑上组合在一起。这种由过程到包的组合就是代码的模块化。包的使用意味着只需要管理更少的文件和更少的模块。对于程序员来说更容易做到模块的重用。迁移过程包括将这些过程体分别复制到同一个包体中。过程接口定义成为包规范。最后可以通过添加新的过程和函数来加强
8、包的整体功能。完成包的合并后,首先编译包规范,然后编译包体。1. PACKAGEapplication_namep1;p2;application_name;6. PACKAGEp19. PL/SQLcode 10. 11. p212. 13. 14. 15. ENDPACKAGE application_name IS PROCEDURE p1; PROCEDURE p2;END application_name;PACKAGE BODY application_name IS PROCEDURE p1 IS PL/SQL code END p1; PROCEDURE p2 IS END p
9、2;四、包规范 PL/SQL语言要求将一个程序集合的接口编译成为单一的程序单元。这个单元,也就是包规范。这只是定义了API接口。而应用逻辑的具体实现则包含在包体中。包规范可以是一个单独的ASCII文本文件,能编译成单一程序单元。包体也可以是一个单独的ASCII文本文件。必须首先成功编译包规范,然后才能编译包体。可以把包规范和包体放入同一个文件中。1.语法与格式 最基本的包规范语法是:package_nameTypedefinitionsforrecords,index-bytables,varrays,nestedtables3. Constants 4. Exceptions 5. Glob
10、alvariabledeclarations 6. PROCEDUREprocedure_name_1(parameters&types);7. FUNCTIONfunction_name_1types)type;8. ENDpackage_name;CREATE PACKAGE package_name IS Type definitions for records, index-by tables, varrays, nested tables ConstantsExceptionsGlobal variable declarationsPROCEDURE procedure_name_1
11、 (parameters & types);FUNCTION function_name_1 (parameters & types) RETURN type;END package_name; 包规范对过程和函数出现的顺序没有要求。而且包规范中的每个子程序都必须有一个与之相对应的子程序体。包规范可以声明数据类型,数据声明和异常。在包规范中声明的所有数据对象都是全局的。所以在包规范声明的变量只是那些作用域是全局的变量。 包体中的PROCEDURE语句必须与相应包规范中的PROCEDURE语句相匹配。包括子程序名称、参数名称、参数模式和参数类型等。这一要求同样适用于FUNCTION;包规范可以声
12、明异常。异常或者全部声明在规范开头,或者全部声明在规范结尾。Invalie_operationEXCEPTOIN;(parameters 5. END Invalie_operation EXCEPTOIN; PROCEDURE procedure_name_1 ( parameters & 处理异常的应用程序代码类似于:1. BEGINothercode,etc package_name.procedure_name_1(parameters);5. EXCEPTION WHENpackage_name.invalid_operationTHENdosomething;7. END; oth
13、er code, etc package_name.procedure_name_1(parameters);EXCEPTION WHEN package_name.invalid_operation THEN do something;END;五、参数与模式 PL/SQL有三种模式:1. IN(默认) 传给子程序的IN模式参数表明 了子程序只能将该参数作为一个常量来使用。这是只读的。作为IN模式的参数可以是一个文字表达式、常量声明或者变量声明。当参数为变量时,该模式提供了安全措施保证正确的程序调用。调用程序能够了解在完成调用后,该变量的值没有发生改变。下面的过程不能编译,原因是对IN模式变量
14、进行了写操作。print_next_value( v_dataININTEGER3. ) -compileerror dbms_output.put_line(v_data);7. dbms_output.put_line(v_data+correct 8. END;PROCEDURE print_next_value ( v_data IN INTEGER ) v_data := v_data +1 ;-compile error dbms_output.put_line(v_data);dbms_output.put_line(v_data + 1); -compile correct2.
15、 IN OUT 能够通过这种模式传递的参数只能是变量类型,不允许为文字或者常量。前提是被调用的过程将会改变传递的内容。被调过程也能对其进行读写操作。当查看一个具有IN OUT模式参数的过程时,要求调用程序在调用该过程时必须提供数据。这是IN OUT参数中IN部分的要求。change_dataOUT3. )4. BGIN iin1.10loop +1;endloop;change_data;PROCEDURE change_data ( v_data IN OUT INTEGER) ISBGIN for i in 1.10 loop v_data := v_data +1; end loop;E
16、ND change_data;块调用 1. DECLAREmy_data=0;-不能为常量 3. BEGINchange_data(my_data);dbms_output.put_line(blockprint:my_data);-10 6. END;DECLARE my_data INTEGER :-不能为常量 change_data(my_data); dbms_output.put_line(block print: | my_data);-103. OUT 能够通过这种模式传递参数只能是变量类型。不允许为文字或者常量。在子程序中,一个OUT模式参数的初始值为NULL。使用OUT模式参
17、数的目的在于传递关于接口的信息。调用过程不必为被调过程传递参数。被调过程完成对数据结构的读写操作。provide_data( 100;8. endprovide_data;PROCEDURE provide_data( v_data OUT INTEGER= 100; v_data :end loop;END provide_data;块中调用 insertintotempvalues(my_data);-0 provide_data(my_data)-110 insert into temp values(my_data);-0 provide_data(my_data) ;-110六、函数
18、与模式 函数常常用名词来命名,而过程则常用动词来命名。在所有应用程序中,绝大多数的函数参数都是IN 模式的。但是函数参数的模式可以是所有这3种模式。下面展示了关于一个函数的设计,该函数返回数据和状态信息。对于这个接口,假定ARG1是主键,用来精确确定需要获取的记录。参数next_rec是需要的数据。1. FUNCTIONnext_rec(arg1type,next_recordtype) 2. RETURNBOOLEAN;FUNCTION next_rec( arg1 IN type, next_record OUT type)RETURN BOOLEAN;这种设计允许用户编写如下代码:1.
19、WHILEnext_rec(arg1,my_record_structure) 2. LOOP processmy_record_structure;LOOP;WHILE ( next_rec(arg1,my_record_structure) )LOOP process my_record_structure;END LOOP;可以通过下面的过程来代替函数:get_next_rec( 2. arg1type, 3. next_record4. statusBOOLEAN 5. );PROCEDURE get_next_rec(arg1 IN type,next_record OUT type,status OUT BOOLEAN使用:1. LOOP get_next_rec(arg1,my_record_structure,status);EXITNOTstatus; get_next_rec(arg1,my_record_structure,status); EXIT WHEN NO