zoukankan      html  css  js  c++  java
  • 过程与函数

    过程和函数统称为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语句内部(如表达式)调用函数来完成复杂的计算问题,但不能调用过程。所以这是函数的特色。

  • 相关阅读:
    django 项目运行时static静态文件不能加载问题处理
    django 项目运行时media静态文件不能加载问题处理
    django 的用户验证及登录状态保持
    django 2.0 中URL的include方法使用分析
    auth.User.groups: (fields.E304)
    web理论知识--HTML结构及标签
    数据库相关--mysql中的单表查询
    python基础下的数据结构与算法之链表
    python基础下的数据结构与算法之顺序表
    Nginx 日志分析命令
  • 原文地址:https://www.cnblogs.com/rxhuiu/p/9111861.html
Copyright © 2011-2022 走看看