Oracle 存储过程、函数与触发器

关键词:Oracle 存储过程、函数、触发器、包、PL/SQL 编程


✅ 摘要

在企业级 Oracle 数据库开发中,存储过程(Procedure)、函数(Function)和触发器(Trigger) 是构建复杂业务逻辑、提高系统性能、实现数据一致性的核心组件。

本文将围绕 Oracle 中的 PL/SQL 程序结构 展开讲解:

  • 创建与调用存储过程(支持 IN/OUT 参数)
  • 创建与使用函数(RETURN 返回值)
  • 使用 DBMS_OUTPUT 调试输出
  • 触发器类型与应用场景(DML 触发器、INSTEAD OF 触发器)
  • 包(Package)的创建与封装(组织多个过程和函数)

每部分都配有 完整的 PL/SQL 示例代码,适合初学者学习掌握,也适合中级开发者深入理解。


一、存储过程与函数

🔹 1. 创建存储过程(支持 IN/OUT 参数)

示例:计算两个数之和并返回结果
sql 复制代码
CREATE OR REPLACE PROCEDURE add_numbers (
    num1 IN NUMBER,
    num2 IN NUMBER,
    result OUT NUMBER
)
IS
BEGIN
    result := num1 + num2;
    DBMS_OUTPUT.PUT_LINE('两数之和为: ' || result);
END;
调用方式:
sql 复制代码
DECLARE
    v_result NUMBER;
BEGIN
    add_numbers(5, 3, v_result);
    DBMS_OUTPUT.PUT_LINE('调用后的结果是: ' || v_result);
END;

🔹 2. 创建函数(RETURN 返回值)

示例:根据员工ID查询其工资
sql 复制代码
CREATE OR REPLACE FUNCTION get_salary (emp_id IN NUMBER)
RETURN NUMBER
IS
    v_salary NUMBER;
BEGIN
    SELECT salary INTO v_salary
    FROM employees
    WHERE employee_id = emp_id;

    RETURN v_salary;
EXCEPTION
    WHEN NO_DATA_FOUND THEN
        RETURN NULL;
END;
调用方式:
sql 复制代码
DECLARE
    v_salary NUMBER;
BEGIN
    v_salary := get_salary(100);
    IF v_salary IS NOT NULL THEN
        DBMS_OUTPUT.PUT_LINE('员工工资为: ' || v_salary);
    ELSE
        DBMS_OUTPUT.PUT_LINE('未找到该员工');
    END IF;
END;

🔹 3. 使用 DBMS_OUTPUT 输出调试信息

sql 复制代码
SET SERVEROUTPUT ON; -- 必须先开启输出

BEGIN
    DBMS_OUTPUT.PUT_LINE('这是调试信息');
END;

二、触发器(Trigger)

🔹 1. DML 触发器:在表操作前后自动执行

示例:记录员工表更新日志
sql 复制代码
CREATE TABLE emp_log (
    log_id      NUMBER GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY,
    operation   VARCHAR2(10),
    emp_id      NUMBER,
    old_salary  NUMBER,
    new_salary  NUMBER,
    change_time TIMESTAMP DEFAULT SYSTIMESTAMP
);

CREATE OR REPLACE TRIGGER trg_emp_update
AFTER UPDATE ON employees
FOR EACH ROW
BEGIN
    INSERT INTO emp_log (operation, emp_id, old_salary, new_salary)
    VALUES ('UPDATE', :OLD.employee_id, :OLD.salary, :NEW.salary);
END;
测试语句:
sql 复制代码
UPDATE employees SET salary = 8000 WHERE employee_id = 100;
SELECT * FROM emp_log;

🔹 2. INSTEAD OF 触发器:用于视图上的 DML 操作

示例:为只读视图添加插入功能
sql 复制代码
CREATE OR REPLACE VIEW emp_info_view AS
SELECT employee_id, first_name, last_name, department_id
FROM employees;

CREATE OR REPLACE TRIGGER trg_insert_emp_info
INSTEAD OF INSERT ON emp_info_view
BEGIN
    INSERT INTO employees(employee_id, first_name, last_name, department_id)
    VALUES (:NEW.employee_id, :NEW.first_name, :NEW.last_name, :NEW.department_id);
END;
测试插入:
sql 复制代码
INSERT INTO emp_info_view(employee_id, first_name, last_name, department_id)
VALUES (1001, 'Tom', 'Smith', 60);

三、包(Package)

🔹 1. 包的组成:规范(Specification) + 主体(Body)

部分 描述
Package Specification 声明变量、常量、过程、函数接口
Package Body 实现声明的逻辑

🔹 2. 创建包规范(Spec)

sql 复制代码
CREATE OR REPLACE PACKAGE emp_pkg IS
    PROCEDURE update_salary(emp_id IN NUMBER, new_salary IN NUMBER);
    FUNCTION get_fullname(emp_id IN NUMBER) RETURN VARCHAR2;
END emp_pkg;

🔹 3. 创建包主体(Body)

sql 复制代码
CREATE OR REPLACE PACKAGE BODY emp_pkg IS

    PROCEDURE update_salary(emp_id IN NUMBER, new_salary IN NUMBER) IS
    BEGIN
        UPDATE employees
        SET salary = new_salary
        WHERE employee_id = emp_id;
    END;

    FUNCTION get_fullname(emp_id IN NUMBER) RETURN VARCHAR2 IS
        v_name VARCHAR2(100);
    BEGIN
        SELECT first_name || ' ' || last_name INTO v_name
        FROM employees
        WHERE employee_id = emp_id;

        RETURN v_name;
    END;

END emp_pkg;

🔹 4. 调用包中的方法

sql 复制代码
BEGIN
    emp_pkg.update_salary(100, 9000);
    DBMS_OUTPUT.PUT_LINE('姓名为: ' || emp_pkg.get_fullname(100));
END;

✅ 总结

以下内容为主要点:

模块 技能点
存储过程 支持输入输出参数的过程定义与调用
函数定义 使用 RETURN 返回值,处理异常
触发器机制 DML 触发器、INSTEAD OF 触发器
包的使用 封装多个过程和函数,提升模块化能力
实战应用 审计日志、视图增删改、业务封装等场景

这些技能是你成为 Oracle 数据库高级开发者的必备基础。建议你将文中示例复制到本地环境中运行练习,加深理解。


📚 参考资料

相关推荐
计算机毕设VX:Fegn089510 小时前
计算机毕业设计|基于springboot + vue医院设备管理系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
Mr__Miss11 小时前
保持redis和数据库一致性(双写一致性)
数据库·redis·spring
Knight_AL12 小时前
Spring 事务传播行为 + 事务失效原因 + 传播行为为什么不用其他模式
数据库·sql·spring
倔强的石头_12 小时前
时序数据时代的“存储与分析困局”解析及金仓解决方案
数据库
计算机毕设VX:Fegn089512 小时前
计算机毕业设计|基于springboot + vue小型房屋租赁系统(源码+数据库+文档)
数据库·vue.js·spring boot·后端·课程设计
倔强的石头_13 小时前
场景化落地指南——金仓时序数据库在关键行业的应用实践
数据库
SelectDB13 小时前
驾驭 CPU 与编译器:Apache Doris 实现极致性能的底层逻辑
运维·数据库·apache
zbguolei13 小时前
MySQL根据身份证号码计算出生日期和年龄
数据库·mysql
马克学长14 小时前
SSM校园图书借阅服务系统jd2z8(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面
数据库·图书管理系统·ssm 框架·ssm 校园图书借阅系统
软件派14 小时前
高斯数据库使用心得——从性能优化到行业实践的深度解析
数据库·oracle