过程与函数

过程和函数统称为PL/SQL子程序,他们是被命名的PL/SQL块,被编译后存储在数据库中,并通过输入、输出参数或输入/输出参数与其调用者交换信息。过程和函数的唯一区别是函数总向调用者返回数据,而过程则不返回数据

一 创建函数

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 过程与函数的比较 

使用过程与函数具有如下优点:

1、共同使用的代码可以只需要被编写和测试一次,而被需要该代码的任何应用程序(如:.NET、C++、JAVA、VB程序,也可以是DLL库)调用。

2、这种集中编写、集中维护更新、大家共享(或重用)的方法,简化了应用程序的开发和维护,提高了效率与性能。

3、这种模块化的方法,使得可以将一个复杂的问题、大的程序逐步简化成几个简单的、小的程序部分,进行分别编写、调试。因此使程序的结构清晰、简单,也容易实现。

4、可以在各个开发者之间提供处理数据、控制流程、提示信息等方面的一致性。

5、节省内存空间。它们以一种压缩的形式被存储在外存中,当被调用时才被放入内存进行处理。并且,如果多个用户要执行相同的过程或函数时,就只需要在内存中加载一个该过程或函数。

6、提高数据的安全性与完整性。通过把一些对数据的操作放到过程或函数中,就可以通过是否授予用户有执行该过程或的权限,来限制某些用户对数据进行这些操作。

过程与函数的相同功能有:

1、 都使用IN模式的参数传入数据、OUT模式的参数返回数据。

2、 输入参数都可以接受默认值,都可以传值或传引导。

3、 调用时的实际参数都可以使用位置表示法、名称表示法或组合方法。

4、 都有声明部分、执行部分和异常处理部分。

5、 其管理过程都有创建、编译、授权、删除、显示依赖关系等。

使用过程与函数的原则:

1、如果需要返回多个值和不返回值,就使用过程;如果只需要返回一个值,就使用函数。

2、过程一般用于执行一个指定的动作,函数一般用于计算和返回一个值。

3、可以SQL语句内部(如表达式)调用函数来完成复杂的计算问题,但不能调用过程。所以这是函数的特色。

原文地址:https://www.cnblogs.com/rxhuiu/p/9111861.html

时间: 2024-08-29 20:24:00

过程与函数的相关文章

ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!)

原文:ORACLE PL/SQL编程之六:把过程与函数说透(穷追猛打,把根儿都拔起!) ORACLE PL/SQL编程之六: 把过程与函数说透(穷追猛打,把根儿都拔起!)   继上篇:ORACLE PL/SQL编程之八:把触发器说透 得到了大家的强力支持,感谢.接下来再下猛药,介绍下一篇,大家一定要支持与推荐呀~!我也才有动力写后面的.   本篇主要内容如下: 6.1 引言 6.2 创建函数 6.3 存储过程 6.3.1 创建过程 6.3.2 调用存储过程 6.3.3 AUTHID 6.3.4 

第六课 过程与函数

这讲是核心重点***** 什么是过程?什么又是函数?过程和函数在delphi中无处不再.过程简单的理解就是单击一个按钮这就是一个过程,函数和过程不一样的地方就是函数能把这个过程的结果返回给我们,过程的关键字用procedure ,函数的关键字Function  下面就具体讲解过程与函数的定义 过程与函数 Pascal中的例程有两种形式:过程和函数.理论上说,过程是你要求计算机执行的操作,函数是能返回值的计算.两者突出的不同点在于:函数能返回计算结果,即有一个返回值,而过程没有.两种类型的例程都可

Delphi过程、函数传递参数的八种方式

Delphi过程函数传递参数的八种方式 Delphi过程.函数传递参数的八种方式,布布扣,bubuko.com

DELPHI——过程与函数[delphi]

原文来自:http://my.oschina.net/pc100/blog/380016 过程以保留字procedure开始,没有返回值:函数以保留字function开始,有返回值. 参数位于括号里面,多个参数之间以分号分隔,例如: procedure SetDate(Year: Integer; Month: Integer; Day: Integer); 也可以将相同类型的参数组合在一起,则上述过程标题写成: procedure SetDate(Year, Month, Day: Integ

Oracle过程及函数的参数模式详解

一.In.out.in out模式 在Oracle中过程与函数都可以有参数,参数的类型可以指定为in.out.in out三种模式. 三种参数的具体说明,如下图所示: (1)in模式 in模式是引用传递.调用过程时实际参数将值以引用方式传递给存储过程的形式参数,形式参数在过程中是只读模式的,也就是说:只能通过形式参数读取到实际参数的值.当过程执行完毕后,实际参数的值不会发生任何变化. 过程: create or replace procedure MyProcedure(param1 in IN

为过程或函数sp_Adduser指定了过多的参数

前些天写用户注册模块,用存储过程添加用户,一开始就报“为过程或函数sp_Adduser指定了过多的参数”.仔细检查数据层的用户添加函数,结果在为存储过程添加sqlparameter参数的时候,数组给写错位了(参数太多).改正后,编译执行,结果还是报“为过程或函数sp_Adduser指定了过多的参数”.自己把存储过程程序对照了好几遍,没问题.到网上搜索,原来在执行存储过程的时候,如果以sp开头,用户创建的存储过程,总会先检查master数据库(即使该存储过程已用数据库名称限定).   如果用户创建

Oracle数据库之PL/SQL过程与函数

Oracle数据库之PL/SQL过程与函数 PL/SQL块分为匿名块与命名块,命名块又包含子程序.包和触发器. 过程和函数统称为PL/SQL子程序,我们可以将商业逻辑.企业规则写成过程或函数保存到数据库中,以便共享. 过程和函数均存储在数据库中,并通过参数与其调用者交换信息.过程和函数的唯一区别是函数总向调用者返回数据,而过程不返回数据. 1. 存储过程概念 存储过程(Stored Procedure)是在大型数据库系统中,一组为了完成特定功能的SQL语句集,存储在数据库中.经过第一次编译后再次

存储过程-“为过程或函数指定了过多的参数”的错误

最近在忙公司的一个项目,其中一个模块要用到存储过程,在程序中存储过程的具体执行过程中竟然报了"为过程或函数指定了过多的参数"的错误.仔细比较程序中的存储过程与数据库中的定义,发现两者并未出现差别.没法,只有硬着头皮一点一点的比对,半个小时过去了还是未找到错误的根源.无奈之下,只好请教其他大神.大神不愧是大神吗,只问了我一句,你的库确定连对了吗?顿时觉醒了,我配置文件中连接的是远程库,改为本地库以后程序顺利进行. 在解决问题百度的过程中,我发现出现这个错误还可能是以下几种情况: 1.存储

Delphi之过程与函数

过程以保留字procedure开始,没有返回值:函数以保留字function开始,有返回值. 参数位于括号里面,多个参数之间以分号分隔,例如: procedure SetDate(Year: Integer; Month: Integer; Day: Integer); 也可以将相同类型的参数组合在一起,则上述过程标题写成: procedure SetDate(Year, Month, Day: Integer); 函数在标题中还多了一项——返回值的类型.下面是一个返回值为Double型的函数标

pl/sql可以封装代码的结构(过程,函数, 包)

1.过程(procedure) what:执行特定的操作 why:封装代码,提高代码重用率,易于维护. style:可以返回多个数据(输入参数IN,输出参数OUT) sample: create procedure name_pro (IN partment1 datatype, IN partment2 datatype, out partment2 datatype) is begin ---sql/plsql执行代码 end; / 2.函数 what:执行数据操作,返回特定的数据 why: