过程和函数统称为PL/SQL子程序,他们是被命名的PL/SQL块,被编译后存储在数据库中,并经过输入、输出参数或输入/输出参数与其调用者交换信息。过程和函数的惟一区别是函数总向调用者返回数据,而过程则不返回数据。数据库
一 建立函数express
1 建立函数安全
语法:模块化
1 CREATE [OR REPLACE] FUNCTION function_name 2 (arg1 [ { IN | OUT | IN OUT }] type1 [DEFAULT value1], 3 [arg2 [ { IN | OUT | IN OUT }] type2 [DEFAULT value1]], 4 ...... 5 [argn [ { IN | OUT | IN OUT }] typen [DEFAULT valuen]]) 6 [ AUTHID DEFINER | CURRENT_USER ] 7 RETURN return_type 8 IS | AS 9 <类型.变量的声明部分>
10 BEGIN 11 执行部分 12 RETURN expression 13 EXCEPTION 14 异常处理部分 15 END function_name;
i. IN,OUT,IN OUT是形参的模式。若省略,则为IN模式。IN模式的形参只能将实参传递给形参,进入函数内部,但只能读不能写,函数返回时实参的值不变。OUT模式的形参会忽略调用时的实参值(或说该形参的初始值老是NULL),但在函数内部能够被读或写,函数返回时形参的值会赋予给实参。IN OUT具备前两种模式的特性,即调用时,实参的值老是传递给形参,结束时,形参的值传递给实参。调用时,对于IN模式的实参能够是常量或变量,但对于OUT和IN OUT模式的实参必须是变量。函数
ii. 通常,只有在确认function_name函数是新函数或是要更新的函数时,才使用OR REPALCE关键字,不然容易删除有用的函数。工具
例子: 获取某部门的工资总和性能
1 --获取某部门的工资总和 2 CREATE OR REPLACE 3 FUNCTION get_salary( 4 Dept_no NUMBER, 5 Emp_count OUT NUMBER) 6 RETURN NUMBER 7 IS 8 V_sum NUMBER; 9 BEGIN 10 SELECT SUM(SALARY), count(*) INTO V_sum, emp_count 11 FROM EMPLOYEES WHERE DEPARTMENT_ID=dept_no; 12 RETURN v_sum; 13 EXCEPTION 14 WHEN NO_DATA_FOUND THEN 15 DBMS_OUTPUT.PUT_LINE('你须要的数据不存在!'); 16 WHEN OTHERS THEN 17 DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM); 18 END get_salary;
2 函数的调用开发工具
函数声明时所定义的参数称为形式参数,应用程序调用时为函数传递的参数称为实际参数。应用程序在调用函数时,可使用如下三种方法向函数传递参数:测试
第一种参数传递格式:位置表示法编码
即在调用时按形参的排列顺序,依次写出实参的名称,而将形参与实参关联起来进行传递。用这种方法进行调用,形参与实参的名称是相互独立,没有关系,强调次序才是重要的。格式为:
argument_value1[,argument_value2 …]
例子:计算某部门的工资总和
1 DECLARE 2 V_num NUMBER; 3 V_sum NUMBER; 4 BEGIN 5 V_sum :=get_salary(10, v_num); 6 DBMS_OUTPUT.PUT_LINE('部门号为:10的工资总和:'||v_sum||',人数为:'||v_num); 7 END;
第二种参数传递格式:名称表示法
即在调用时按形参的名称与实参的名称,写出实参对应的形参,而将形参与实参关联起来进行传递。这种方法,形参与实参的名称是相互独立的,没有关系,名称的对应关系才是最重要的,次序并不重要。格式为:
argument => parameter [,…]
其中:argument为形式参数,它必须与函数定义时所声明的形式参数名称相同parameter为实际参数。
在这种格式中,形势参数与实际参数成对出现,相互间关系惟一肯定,因此参数的顺序能够任意排列。
例子:计算某部门的工资总和
1 DECLARE 2 V_num NUMBER; 3 V_sum NUMBER; 4 BEGIN 5 V_sum :=get_salary(emp_count => v_num, dept_no => 10); 6 DBMS_OUTPUT.PUT_LINE('部门号为:10的工资总和:'||v_sum||',人数为:'||v_num); 7 END;
第三种参数传递格式:组合传递
即在调用一个函数时,同时使用位置表示法和名称表示法为函数传递参数。采用这种参数传递方法时,使用位置表示法所传递的参数必须放在名称表示法所传递的参数前面。也就是说,不管函数具备多少个参数,只要其中有一个参数使用名称表示法,其后全部的参数都必须使用名称表示法。
例子:
1 CREATE OR REPLACE FUNCTION demo_fun( 2 Name VARCHAR2, --注意VARCHAR2不能给精度,如:VARCHAR2(10),其它相似 3 Age INTEGER, 4 Sex VARCHAR2) 5 RETURN VARCHAR2 6 AS 7 V_var VARCHAR2(32); 8 BEGIN 9 V_var := name||':'||TO_CHAR(age)||'岁.'||sex; 10 RETURN v_var; 11 END; 12
13 DECLARE 14 Var VARCHAR(32); 15 BEGIN 16 Var := demo_fun('user1', 30, sex => '男'); 17 DBMS_OUTPUT.PUT_LINE(var); 18
19 Var := demo_fun('user2', age => 40, sex => '男'); 20 DBMS_OUTPUT.PUT_LINE(var); 21
22 Var := demo_fun('user3', sex => '女', age => 20); 23 DBMS_OUTPUT.PUT_LINE(var); 24 END;
不管采用哪种参数传递方法,实际参数和形式参数之间的数据传递只有两种方法:传址法和传值法。所谓传址法是指在调用函数时,将实际参数的地址指针传递给形式参数,使形式参数和实际参数指向内存中的同一区域,从而实现参数数据的传递。这种方法又称做参照法,即形式参数参照实际参数数据。输入参数均采用传址法传递数据。
传值法是指将实际参数的数据拷贝到形式参数,而不是传递实际参数的地址。默认时,输出参数和输入/输出参数均采用传值法。在函数调用时,ORACLE将实际参数数据拷贝到输入/输出参数,而当函数正常运行退出时,又将输出形式参数和输入/输出形式参数数据拷贝到实际参数变量中。
3 参数默认值
在CREATE OR REPLACE FUNCTION语句中声明函数参数时可使用 DEFAULT 关键字为输入参数指定默认值。
实例:
1 CREATE OR REPLACE FUNCTION demo_fun( 2 Name VARCHAR2, 3 Age INTEGER, 4 Sex VARCHAR2 DEFAULT '男') 5 RETURN VARCHAR2 6 AS 7 V_var VARCHAR2(32); 8 BEGIN 9 V_var := name||':'||TO_CHAR(age)||'岁.'||sex; 10 RETURN v_var; 11 END;
具备默认值的函数建立后,在函数调用时,若是没有为具备默认值的参数提供实际参数值,函数将使用该参数的默认值。但当调用者为默认参数提供实际参数时,函数将使用实际参数值。在建立函数时,只能为输入参数设置默认值,而不能为输入/输出参数设置默认值。
1 DECLARE 2 var VARCHAR(32); 3 BEGIN 4 Var := demo_fun('user1', 30); 5 DBMS_OUTPUT.PUT_LINE(var); 6 Var := demo_fun('user2', age => 40); 7 DBMS_OUTPUT.PUT_LINE(var); 8 Var := demo_fun('user3', sex => '女', age => 20); 9 DBMS_OUTPUT.PUT_LINE(var); 10 END;
二 存储过程
1 建立过程
在ORACLE SERVER上创建存储过程,能够被多个应用程序调用,能够向存储过程传递参数,也能够向存储过程传回参数.
建立过程语法:
1 CREATE [OR REPLACE] PROCEDURE procedure_name 2 ([arg1 [ IN | OUT | IN OUT ]] type1 [DEFAULT value1], 3 [arg2 [ IN | OUT | IN OUT ]] type2 [DEFAULT value1]], 4 ...... 5 [argn [ IN | OUT | IN OUT ]] typen [DEFAULT valuen]) 6 [ AUTHID DEFINER | CURRENT_USER ] 7 { IS | AS } 8 <声明部分>
9 BEGIN 10 <执行部分>
11 EXCEPTION 12 <可选的异常错误处理程序>
13 END procedure_name;
实例:
用户链接登记记录
1 CREATE TABLE logtable (userid VARCHAR2(10), logdate date); 2
3 CREATE OR REPLACE PROCEDURE logexecution 4 IS 5 BEGIN 6 INSERT INTO logtable (userid, logdate) VALUES (USER, SYSDATE); 7 END;
删除指定员工记录
1 CREATE OR REPLACE 2 PROCEDURE DelEmp 3 (v_empno IN employees.employee_id%TYPE) 4 AS 5 No_result EXCEPTION; 6 BEGIN 7 DELETE FROM employees WHERE employee_id = v_empno; 8 IF SQL%NOTFOUND THEN 9 RAISE no_result; 10 END IF; 11 DBMS_OUTPUT.PUT_LINE('编码为'||v_empno||'的员工已被删除!'); 12 EXCEPTION 13 WHEN no_result THEN 14 DBMS_OUTPUT.PUT_LINE('舒适提示:你须要的数据不存在!'); 15 WHEN OTHERS THEN 16 DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM); 17 END DelEmp;
插入员工记录
1 CREATE OR REPLACE 2 PROCEDURE InsertEmp( 3 v_empno in employees.employee_id%TYPE, 4 v_firstname in employees.first_name%TYPE, 5 v_lastname in employees.last_name%TYPE, 6 v_deptno in employees.department_id%TYPE 7 ) 8 AS 9 empno_remaining EXCEPTION; 10 PRAGMA EXCEPTION_INIT(empno_remaining, -1); 11 /* -1 是违反惟一约束条件的错误代码 */
12 BEGIN 13 INSERT INTO EMPLOYEES(EMPLOYEE_ID, FIRST_NAME, LAST_NAME, HIRE_DATE,DEPARTMENT_ID) 14 VALUES(v_empno, v_firstname,v_lastname, sysdate, v_deptno); 15 DBMS_OUTPUT.PUT_LINE('舒适提示:插入数据记录成功!'); 16 EXCEPTION 17 WHEN empno_remaining THEN 18 DBMS_OUTPUT.PUT_LINE('舒适提示:违反数据完整性约束!'); 19 WHEN OTHERS THEN 20 DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM); 21 END InsertEmp;
使用存储过程向departments表中插入数据
1 CREATE OR REPLACE 2 PROCEDURE insert_dept 3 (v_dept_id IN departments.department_id%TYPE, 4 v_dept_name IN departments.department_name%TYPE, 5 v_mgr_id IN departments.manager_id%TYPE, 6 v_loc_id IN departments.location_id%TYPE) 7 IS 8 ept_null_error EXCEPTION; -- 用户定义的异常处理 9 PRAGMA EXCEPTION_INIT(ept_null_error, -1400); 10 ept_no_loc_id EXCEPTION; -- 用户定义的异常处理 11 PRAGMA EXCEPTION_INIT(ept_no_loc_id, -2291); 12 BEGIN 13 INSERT INTO departments 14 (department_id, department_name, manager_id, location_id) 15 VALUES 16 (v_dept_id, v_dept_name, v_mgr_id, v_loc_id); 17 DBMS_OUTPUT.PUT_LINE('插入部门'||v_dept_id||'成功'); 18 EXCEPTION 19 WHEN DUP_VAL_ON_INDEX THEN 20 RAISE_APPLICATION_ERROR(-20000, '部门编码不能重复'); 21 WHEN ept_null_error THEN 22 RAISE_APPLICATION_ERROR(-20001, '部门编码、部门名称不能为空'); 23 WHEN ept_no_loc_id THEN 24 RAISE_APPLICATION_ERROR(-20002, '没有该地点'); 25 END insert_dept; 26
27 -- 调用实例: 28 DECLARE 29 ept_20000 EXCEPTION; 30 PRAGMA EXCEPTION_INIT(ept_20000, -20000); 31 ept_20001 EXCEPTION; 32 PRAGMA EXCEPTION_INIT(ept_20001, -20001); 33 ept_20002 EXCEPTION; 34 PRAGMA EXCEPTION_INIT(ept_20002, -20002); 35 BEGIN 36 insert_dept(300, '部门300', 100, 2400); 37 insert_dept(310, NULL, 100, 2400); 38 insert_dept(310, '部门310', 100, 900); 39
40 /*
41 insert_dept(v_dept_name => '部门310', v_dept_id => 310, 42 v_mgr_id => 100, v_loc_id => 2400); 43 insert_dept(320, '部门320', v_mgr_id => 100, v_loc_id => 900); 44 */
45 EXCEPTION 46 WHEN ept_20000 THEN 47 DBMS_OUTPUT.PUT_LINE('ept_20000部门编码不能重复'); 48 WHEN ept_20001 THEN 49 DBMS_OUTPUT.PUT_LINE('ept_20001部门编码、部门名称不能为空'); 50 WHEN ept_20002 THEN 51 DBMS_OUTPUT.PUT_LINE('ept_20002没有该地点'); 52 WHEN OTHERS THEN 53 DBMS_OUTPUT.PUT_LINE('others出现了其余异常错误'); 54 END;
2 调用存储过程
存储过程创建完成后,只要经过受权,用户就能够在SQLPLUS 、ORACLE开发工具或第三方开发工具中来调用运行。对于参数的传递也有三种:按位置传递、按名称传递和组合传递,传递方法与函数的同样。ORACLE 使用 EXECUTE 语句来实现对存储过程的调用:
EXEC[UTE] procedure_name( parameter1, parameter2…);
好比:
EXECUTE logexecution;
实例:
查询指定员工记录
1 CREATE OR REPLACE 2 PROCEDURE QueryEmp 3 (v_empno IN employees.employee_id%TYPE, 4 v_ename OUT employees.first_name%TYPE, 5 v_sal OUT employees.salary%TYPE) 6 AS 7 BEGIN 8 SELECT last_name || last_name, salary INTO v_ename, v_sal 9 FROM employees 10 WHERE employee_id = v_empno; 11 DBMS_OUTPUT.PUT_LINE('舒适提示:编码为'||v_empno||'的员工已经查到!'); 12 EXCEPTION 13 WHEN NO_DATA_FOUND THEN 14 DBMS_OUTPUT.PUT_LINE('舒适提示:你须要的数据不存在!'); 15 WHEN OTHERS THEN 16 DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM); 17 END QueryEmp;
18 --调用 19 DECLARE 20 v1 employees.first_name%TYPE; 21 v2 employees.salary%TYPE; 22 BEGIN 23 QueryEmp(100, v1, v2); 24 DBMS_OUTPUT.PUT_LINE('姓名:'||v1); 25 DBMS_OUTPUT.PUT_LINE('工资:'||v2); 26 QueryEmp(103, v1, v2); 27 DBMS_OUTPUT.PUT_LINE('姓名:'||v1); 28 DBMS_OUTPUT.PUT_LINE('工资:'||v2); 29 QueryEmp(104, v1, v2); 30 DBMS_OUTPUT.PUT_LINE('姓名:'||v1); 31 DBMS_OUTPUT.PUT_LINE('工资:'||v2); 32 END;
计算指定部门的工资总和,并统计其中的职工数量
1 CREATE OR REPLACE
2 PROCEDURE proc_demo 3 ( 4 dept_no NUMBER DEFAULT 10, 5 sal_sum OUT NUMBER, 6 emp_count OUT NUMBER
7 ) 8 IS
9 BEGIN
10 SELECT SUM(salary), COUNT(*) INTO sal_sum, emp_count 11 FROM employees WHERE department_id = dept_no; 12 EXCEPTION 13 WHEN NO_DATA_FOUND THEN
14 DBMS_OUTPUT.PUT_LINE('舒适提示:你须要的数据不存在!'); 15 WHEN OTHERS THEN
16 DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM); 17 END proc_demo; 18
19 DECLARE
20 V_num NUMBER; 21 V_sum NUMBER(8, 2); 22 BEGIN
23 Proc_demo(30, v_sum, v_num); 24 DBMS_OUTPUT.PUT_LINE('舒适提示:30号部门工资总和:'||v_sum||',人数:'||v_num); 25 Proc_demo(sal_sum => v_sum, emp_count => v_num); 26 DBMS_OUTPUT.PUT_LINE('舒适提示:10号部门工资总和:'||v_sum||',人数:'||v_num); 27 END;
在PL/SQL 程序中还能够在块内创建本地函数和过程,这些函数和过程不存储在数据库中,但能够在建立它们的PL/SQL 程序中被重复调用。本地函数和过程在PL/SQL 块的声明部分定义,它们的语法格式与存储函数和过程相同,但不能使用CREATE OR REPLACE 关键字。
实例:
创建本地过程,用于计算指定部门的工资总和,并统计其中的职工数量
1 DECLARE
2 V_num NUMBER; 3 V_sum NUMBER(8, 2); 4 PROCEDURE proc_demo 5 ( 6 Dept_no NUMBER DEFAULT 10, 7 Sal_sum OUT NUMBER, 8 Emp_count OUT NUMBER
9 ) 10 IS
11 BEGIN
12 SELECT SUM(salary), COUNT(*) INTO sal_sum, emp_count 13 FROM employees WHERE department_id=dept_no; 14 EXCEPTION 15 WHEN NO_DATA_FOUND THEN
16 DBMS_OUTPUT.PUT_LINE('你须要的数据不存在!'); 17 WHEN OTHERS THEN
18 DBMS_OUTPUT.PUT_LINE(SQLCODE||'---'||SQLERRM); 19 END proc_demo;
20 --调用方法:
21 BEGIN
22 Proc_demo(30, v_sum, v_num); 23 DBMS_OUTPUT.PUT_LINE('30号部门工资总和:'||v_sum||',人数:'||v_num); 24 Proc_demo(sal_sum => v_sum, emp_count => v_num); 25 DBMS_OUTPUT.PUT_LINE('10号部门工资总和:'||v_sum||',人数:'||v_num); 26 END;
3 AUTHID
过程当中的AUTHID指令能够告诉ORACLE,这个过程使用谁的权限运行。默任状况下,存储过程会做为调用者的过程运行,可是具备设计者的特权。这称为设计者权利运行。
实例:
创建过程,使用AUTOID DEFINER
1 Connect HR/qaz 2 DROP TABLE logtable; 3 CREATE table logtable (userid VARCHAR2(10), logdate date); 4
5 CREATE OR REPLACE PROCEDURE logexecution 6 AUTHID DEFINER 7 IS
8 BEGIN
9 INSERT INTO logtable (userid, logdate) VALUES (USER, SYSDATE); 10 END; 11
12 GRANT EXECUTE ON logexecution TO PUBLIC; 13
14 CONNECT / AS SYSDBA 15 GRANT CONNECT TO testuser1 IDENTIFIED BY userpwd1; 16
17 CONNECT testuser1/userpwd1 18 INSERT INTO HR.LOGTABLE VALUES (USER, SYSDATE); 19 EXECUTE HR.logexecution 20
21 CONNECT HR/qaz 22 SELECT * FROM HR.logtable;
创建过程,使用AUTOID CURRENT_USER
1 CONNECT HR/qaz 2
3 CREATE OR REPLACE PROCEDURE logexecution 4 AUTHID CURRENT_USER
5 IS
6 BEGIN
7 INSERT INTO logtable (userid, logdate) VALUES (USER, SYSDATE); 8 END; 9
10 GRANT EXECUTE ON logexecution TO PUBLIC; 11
12 CONNECT testuser1/userpwd1 13 INSERT INTO HR.LOGTABLE VALUES (USER, SYSDATE); 14 EXECUTE HR.logexecution
4 PRAGMA AUTONOMOUS_TRANSACTION(自治事务)
在Oracle中,一个事务是从执行第一个数据管理语言(DML)语句开始,直到执行一个COMMIT语句,提交保存这个事务,或者执行一个ROLLBACK语句,放弃这次操做结束。事务的“要么所有完成,要么什么都没完成”的本性会使将错误信息记入数据库表中变得很困难,由于当事务失败从新运行时,用来编写日志条目的INSERT语句还未完成。
针对这种困境,Oracle提供了一种便捷的方法,即自治事务。自治事务从当前事务开始,在其自身的语境中执行。它们能独立地被提交或从新运行,而不影响正在运行的事务。正由于这样,它们成了编写错误日志表格的理想形式。在事务中检测到错误时,您能够在错误日志表格中插入一行并提交它,而后在不丢失此次插入的状况下回滚主事务。
由于自治事务是与主事务相分离的,因此它不能检测到被修改过的行的当前状态。这就好像在主事务提交以前,它们一直处于单独的会话里,对自治事务来讲,它们是不可用的。然而,反过来状况就不一样了:主事务可以检测到已经执行过的自治事务的结果。
要建立一个自治事务,您必须在匿名块的最高层或者存储过程、函数、数据包或触发的定义部分中,使用PL/SQL中的PRAGMA AUTONOMOUS_TRANSACTION语句。在这样的模块或过程当中执行的SQL Server语句都是自治的。
实例:
创建过程,使用自动事务处理进行日志记录
1 DROP TABLE logtable; 2
3 CREATE TABLE logtable( 4 Username varchar2(20), 5 Dassate_time date, 6 Mege varchar2(60) 7 ); 8
9 CREATE TABLE temp_table( N number ); 10
11 CREATE OR REPLACE PROCEDURE log_message(p_message varchar2) 12 AS
13 PRAGMA AUTONOMOUS_TRANSACTION; 14 BEGIN
15 INSERT INTO logtable VALUES ( user, sysdate, p_message ); 16 COMMIT; 17 END log_message; 18
19 BEGIN
20 Log_message (‘About to insert into temp_table‘); 21 INSERT INTO temp_table VALUES (1); 22 Log_message (‘Rollback to insert into temp_table‘); 23 ROLLBACK; 24 END; 25
26 SELECT * FROM logtable; 27 SELECT * FROM temp_table;
创建过程,没有使用自动事务处理进行日志记录
1 CREATE OR REPLACE PROCEDURE log_message(p_message varchar2) 2 AS
3 BEGIN
4 INSERT INTO logtable VALUES ( user, sysdate, p_message ); 5 COMMIT; 6 END log_message; 7
8 BEGIN
9 Log_message ('About to insert into temp_table'); 10 INSERT INTO temp_table VALUES (1); 11 Log_message ('Rollback to insert into temp_table'); 12 ROLLBACK; 13 END; 14
15 SELECT * FROM logtable; 16 SELECT * FROM temp_table;
5 删除过程和函数
删除过程:可使用DROP PROCEDURE命令对不须要的过程进行删除,语法以下:
DROP PROCEDURE [user.]Procudure_name;
删除函数:可使用DROP FUNCTION 命令对不须要的函数进行删除,语法以下:
1 DROP FUNCTION [user.]Function_name; 2
3 --删除上面实例建立的存储过程与函数
4 DROP PROCEDURE logexecution; 5 DROP PROCEDURE delemp; 6 DROP PROCEDURE insertemp; 7 DROP PROCEDURE fireemp; 8 DROP PROCEDURE queryemp; 9 DROP PROCEDURE proc_demo; 10 DROP PROCEDURE log_message; 11 DROP FUNCTION demo_fun; 12 DROP FUNCTION get_salary;
6 过程与函数的比较
使用过程与函数具备以下优势:
一、共同使用的代码能够只须要被编写和测试一次,而被须要该代码的任何应用程序(如:.NET、C++、JAVA、VB程序,也能够是DLL库)调用。
二、这种集中编写、集中维护更新、你们共享(或重用)的方法,简化了应用程序的开发和维护,提升了效率与性能。
三、这种模块化的方法,使得能够将一个复杂的问题、大的程序逐步简化成几个简单的、小的程序部分,进行分别编写、调试。所以使程序的结构清晰、简单,也容易实现。
四、能够在各个开发者之间提供处理数据、控制流程、提示信息等方面的一致性。
五、节省内存空间。它们以一种压缩的形式被存储在外存中,当被调用时才被放入内存进行处理。而且,若是多个用户要执行相同的过程或函数时,就只须要在内存中加载一个该过程或函数。
六、提升数据的安全性与完整性。经过把一些对数据的操做放到过程或函数中,就能够经过是否授予用户有执行该过程或的权限,来限制某些用户对数据进行这些操做。
过程与函数的相同功能有:
一、 都使用IN模式的参数传入数据、OUT模式的参数返回数据。
二、 输入参数均可以接受默认值,均可以传值或传引导。
三、 调用时的实际参数均可以使用位置表示法、名称表示法或组合方法。
四、 都有声明部分、执行部分和异常处理部分。
五、 其管理过程都有建立、编译、受权、删除、显示依赖关系等。
使用过程与函数的原则:
一、若是须要返回多个值和不返回值,就使用过程;若是只须要返回一个值,就使用函数。
二、过程通常用于执行一个指定的动做,函数通常用于计算和返回一个值。
三、能够SQL语句内部(如表达式)调用函数来完成复杂的计算问题,但不能调用过程。因此这是函数的特点。