当前位置:首页 > 问答 > 正文

ORACLE数据库里那些过程和函数到底咋用,讲得透彻点儿给你听

它俩到底是啥?为啥要用它?

想象一下,你每天都要做一道复杂的菜,红烧肉”,每次做,你都得重新回忆步骤:先切肉、焯水、炒糖色、下锅炖……反反复复,很麻烦,如果你有个菜谱(过程),或者干脆把关键的调味汁提前调好放冰箱(函数),下次直接用,是不是就省事儿多了?

在ORACLE数据库里:

  • 存储过程:就像那份完整的“红烧肉菜谱”,它是一组为了完成特定功能的SQL语句集合,你给它一些原料(比如猪肉、调料),它就能帮你把整个做菜流程走完,它更侧重于“做一件事”这个动作本身,不一定要有直接的结果给你,它可能负责把新员工的信息插入好几个相关的表格里,这是一个完整的流程。
  • 函数:更像你提前调好的“秘制红烧汁”,它也是一段代码,但它核心目的是“计算并返回一个值”,你给它酱油、糖、料酒(输入参数),它混合一下,返回一碗调好的汁给你,函数必须有一个明确的返回值。

为啥要用它们?(来源:基于常见的数据库开发实践总结)

  1. 提高效率:菜谱写好了,就不用每次都重新想步骤,数据库也一样,过程和函数编译一次后,数据库就知道怎么执行了,下次直接用,速度快。
  2. 减少网络流量:假设你的程序在另一台电脑上,要执行十条SQL语句才能完成一个业务,如果没有过程,你得在网络上发送十次请求,但如果把这十条SQL打包成一个过程,你只需要调用一次这个过程名,网络上传送的数据量就小多了。
  3. 方便维护和重用:业务逻辑变了,比如红烧肉以后要加新调料了,你只需要修改“菜谱”(过程)这一处地方就行了,所有调用这个菜谱的程序就都自动用了新方法,不用到成千上万个程序里一个一个去改。
  4. 数据安全:你可以只给用户执行某个过程的权限,而不让他直接操作底层的数据表,你可以让用户通过“申请报销”这个过程来插入数据,但他没法直接去修改报销金额这个字段,更安全。

过程和函数具体咋创建和使用?

存储过程

  • 创建过程(语法来源:ORACLE官方文档CREATE PROCEDURE语句的精简概括)

    基本套路是:

    CREATE OR REPLACE PROCEDURE 过程名 (参数1 模式 数据类型, 参数2 模式 数据类型, ...)
    IS
    -- 这里可以声明一些变量,就像做菜前准备的碗碟
    BEGIN
        -- 这里写核心的SQL语句,你的菜谱步骤
        -- INSERT, UPDATE, DELETE, SELECT ... INTO 等
    END;

    注意那个“模式”:

    • IN:默认模式,输入参数”,你传给过程的“原料”,过程内部只能用,不能改。
    • OUT:输出参数,过程做完事后,通过这个参数把结果“带出来”给你,过程内部可以修改它的值。
    • IN OUT:既能当输入,也能当输出。
  • 举个栗子(例子来源:常见的业务场景模拟) 我们创建一个给员工涨工资的过程:

    CREATE OR REPLACE PROCEDURE raise_salary (
        p_emp_id IN employees.employee_id%TYPE, -- 输入参数:员工ID,类型和employees表的employee_id字段一样
        p_amount IN NUMBER -- 输入参数:涨薪金额
    )
    IS
    BEGIN
        -- 菜谱步骤:更新工资
        UPDATE employees
        SET salary = salary + p_amount
        WHERE employee_id = p_emp_id;
        -- 提交事务(也可以在主程序里提交)
        COMMIT;
        DBMS_OUTPUT.PUT_LINE('员工 ' || p_emp_id || ' 涨薪成功!');
    EXCEPTION
        WHEN NO_DATA_FOUND THEN
            DBMS_OUTPUT.PUT_LINE('找不到该员工!');
    END raise_salary;
  • 调用过程

    -- 在SQLPLUS或者能输出信息的环境下
    BEGIN
        raise_salary(100, 500); -- 给ID为100的员工涨500块钱
    END;

函数

  • 创建函数(语法来源:ORACLE官方文档CREATE FUNCTION语句的精简概括)

    和过程很像,关键区别是必须用RETURN子句声明返回类型,并且函数体内一定要有RETURN语句返回一个值。

    CREATE OR REPLACE FUNCTION 函数名 (参数1 IN 数据类型, ...) RETURN 数据类型
    IS
        -- 变量声明
        结果变量 数据类型;
    BEGIN
        -- 计算逻辑
        SELECT ... INTO 结果变量 ... ; -- 常见操作
        RETURN 结果变量; -- 必须要有!
    END;
  • 举个栗子 创建一个函数,根据部门ID计算该部门的平均工资:

    CREATE OR REPLACE FUNCTION get_avg_salary (p_dept_id IN NUMBER) RETURN NUMBER
    IS
        v_avg_sal NUMBER;
    BEGIN
        SELECT AVG(salary) INTO v_avg_sal
        FROM employees
        WHERE department_id = p_dept_id;
        RETURN NVL(v_avg_sal, 0); -- 如果部门没人,平均工资为NULL,用NVL转为0
    END get_avg_salary;
  • 调用函数: 函数因为有返回值,所以用法灵活得多,可以像使用一个值一样用它。

    -- 在SQL语句中直接使用
    SELECT department_id, get_avg_salary(department_id) as 部门平均工资
    FROM departments;
    -- 在PL/SQL块中赋值给变量
    DECLARE
        avg_sal NUMBER;
    BEGIN
        avg_sal := get_avg_salary(60);
        DBMS_OUTPUT.PUT_LINE('平均工资是:' || avg_sal);
    END;

过程和函数的核心区别总结

  1. 返回值函数必须有且只有一个返回值,像get_avg_salary返回一个数字。过程没有返回值,但可以通过OUT参数返回多个值。
  2. 用法:因为上述区别,函数主要用在表达式里,能出现在SQL语句中SELECT后面、WHERE条件里等,当成一个值来用,而过程是作为一个独立的PL/SQL语句被调用,用CALL或者直接在BEGIN...END块里写名字执行。
  3. 目的函数目的就是计算,然后给你一个结果。过程目的则是执行一个完整的业务操作,可能涉及增删改查多条语句,更像一个“动作”。

简单记:你想得到一个结果(比如算个数、查个状态),用函数,你想完成一个事情(比如审批流程、生成报表数据),用过程

希望这个“厨房菜谱”的比喻能帮你把这俩家伙看得透透的,核心就是封装和重用,让数据库帮你干复杂的活儿,你的应用程序就轻松了。

ORACLE数据库里那些过程和函数到底咋用,讲得透彻点儿给你听