当前位置: 首页 > news >正文

[ORACLE数据库] ORACLE 的 PL/SQL 块

对于刚接触 ORACLE 数据库的初学者来说,PL/SQL 可能是一个既陌生又重要的概念。它不仅是数据库操作的 “进阶工具”,更是实现复杂业务逻辑的核心。

一、什么是 PL/SQL?

PL/SQL(Procedural Language/SQL)是 ORACLE 推出的过程化编程语言,属于第三代语言。它最大的特点是将 SQL 的数据操纵能力与过程化编程结合—— 既可以直接使用 SQL 的查询、插入、更新等操作,又能像 C、Java 一样通过条件判断、循环等逻辑处理复杂业务,因此成为数据库事务处理的强大工具。

二、PL/SQL 块的分类:你需要知道的 5 种类型

PL/SQL 的代码以 “块” 为基本单位,根据功能和使用场景,可分为三大类共 5 种类型,初学者需重点区分它们的特点和用途:

1️⃣基础块:无名块与命名块

  • 无名块(匿名块):动态编写,只能执行一次,可调用其他程序但不能被其他程序调用。适合临时执行的简单逻辑(如一次性数据处理)。
  • 命名块:给无名块加上标签(名称),本质仍是匿名块的变种,主要用于代码标识和嵌套场景。

2️⃣可复用的子程序

存储在数据库中,编译一次后可反复调用,是实现代码复用的核心:

  • 存储过程:一组预定义的 SQL 语句集合,用于完成特定功能(如批量更新数据)。
  • 函数:与存储过程类似,但必须返回一个值,可作为表达式或参数使用(如计算某列的平均值)。

3️⃣自动触发的触发器

无需手动调用,由特定事件(如数据修改、系统启动)触发自动执行:

  • DML 触发器:在表或视图执行 INSERT/UPDATE/DELETE 时触发(如数据删除前自动备份)。
  • 视图替代触发器:解决多表联合视图无法直接修改的问题,替代用户操作执行自定义逻辑。
  • 系统触发器:响应数据库系统事件(如用户登录 / 退出、系统启动)。

4️⃣模块化管理的程序包

类似 Java 的 “包”,用于集中管理存储过程、函数、变量等,实现代码的模块化和封装,方便调用和维护。

三、PL/SQL 的 “规矩”:标识符与变量命名

写 PL/SQL 代码前,必须先掌握标识符(变量、常量等的名称)的规则,否则会频繁报错:

  • 基础限制:长度≤30 字符;首字符必须是字母;不区分大小写;不能用减号 “-”;不能是 SQL 保留字(如 SELECT、INSERT)。
  • 建议命名规范(提升代码可读性):
标识符类型命名规则示例
程序变量v_前缀 + 名称v_ename(表示 “员工姓名变量”)
程序常量c_前缀 + 名称c_company_name(表示 “公司名称常量”)
游标变量Cursor + 名称Cursor_Emp(表示 “员工游标”)
异常标识e_前缀 + 名称e_too_many(表示 “数量过多异常”)
表类型名称 + _table_typeEmp_record_type(表示 “员工记录类型”)

四、入门实战:从无名块开始写代码

无名块是 PL/SQL 最基础的形式,结构简单,适合新手练手。它的固定结构为:

plsql

DECLARE  -- 定义变量(可选)变量声明;
BEGIN    -- 执行逻辑(必选)SQL语句或PL/SQL逻辑;
END;     -- 结束(必选)
/        -- 执行该块(在SQL*Plus中)

示例 1:插入数据并显示结果

plsql

-- 打开输出显示(否则看不到结果)
set serveroutput on;
DECLARErow_id ROWID;  -- 存储行标识info VARCHAR2(40);  -- 存储提示信息
BEGIN-- 插入数据,并将插入的行标识和信息存入变量INSERT INTO scott.dept VALUES (90, '财务室', '海口') RETURNING rowid, dname||':'||to_char(deptno)||':'||loc INTO row_id, info;-- 输出结果(类似Java的System.out.println)DBMS_OUTPUT.PUT_LINE('ROWID:'||row_id);DBMS_OUTPUT.PUT_LINE(info);
END;
/

关键说明:

  • RETURNING:用于获取 INSERT/UPDATE/DELETE 操作影响的数据(如行标识、列值)。
  • DBMS_OUTPUT.PUT_LINE:打印结果到控制台,需先执行set serveroutput on开启。

五、进阶工具:存储过程与函数

当一段逻辑需要反复执行(如每月工资计算),就该用存储过程或函数了 —— 它们存储在数据库中,调用时无需重新编译,效率更高。

1️⃣存储过程:无返回值的 “代码块”

(1)创建存储过程
  • 无参数示例(修改部门名称):

plsql

-- create or replace:若存在则覆盖
create or replace procedure update_my_dept 
is
beginUpdate dept set dname = '销售部' where deptno=40;commit;  -- 提交事务
end;

  • 有参数示例(新增部门):

plsql

create or replace procedure add_my_dept(V_deptno number,  -- 部门编号参数V_dname varchar2, -- 部门名称参数V_loc varchar2    -- 部门位置参数
) 
is
begininsert into my_dept values(V_deptno, V_dname, V_loc);commit;
end;
(2)调用存储过程

plsql

-- 方法1:用exec调用
exec add_my_dept(14, '研发部', '北京');-- 方法2:用call调用
call add_my_dept(17, '市场部', '上海');

2️⃣函数:有返回值的 “计算工具”

函数与存储过程的核心区别是必须返回一个值,常用来做计算或数据转换。

(1)创建函数

plsql

create or replace function hello(str in varchar2)
return varchar2  -- 声明返回值类型
isret varchar2(20);  -- 定义局部变量
beginret := 'Hello, ' || str;  -- 拼接字符串DBMS_OUTPUT.put_line(ret);  -- 打印结果return ret;  -- 返回结果(必须有)
end;
(2)调用函数

plsql

-- 像调用系统函数一样使用
select hello('Oracle') from dual;  -- 输出:Hello, Oracle
(3)注意事项
  • 参数类型不能指定长度(如varchar2不能写成varchar2(20))。
  • 必须有return子句,且函数体内至少有一条return语句。
  • 支持in(输入)、out(输出)、in out(输入输出)参数。

六、自动执行的 “监听器”:触发器

触发器是数据库的 “自动响应机制”—— 当指定事件发生时,自动执行预设逻辑,无需手动调用。

1️⃣触发器的核心组成

  • 触发事件:如 INSERT/UPDATE/DELETE(DML)、登录 / 退出(用户事件)。
  • 触发时间:事件发生前(BEFORE)或后(AFTER)。
  • 触发对象:表、视图、数据库等。
  • 触发条件:用WHEN指定逻辑,为 TRUE 时才执行。
  • 触发频率:语句级(事件发生一次执行一次)或行级(每行触发一次)。

2️⃣实例:删除数据前自动备份

plsql

-- 创建触发器:删除my_dept表中deptno=40的记录时,自动备份到dept_backups
create or replace trigger backup_deptbefore delete  -- 删除前执行on scott.my_dept  -- 监听的表for each row  -- 行级触发(每删一行执行一次)when (old.deptno = 40)  -- 只备份deptno=40的记录
begin-- :old表示“修改前的记录”,存储旧值insert into dept_backups values(:old.deptno, :old.dname, :old.loc, sysdate);
end;

3️⃣系统触发器:监控数据库事件

比如记录用户登录 / 退出时间:

plsql

-- 先创建日志表
create table log_event (user_name varchar2(10),address varchar2(20),logon_date timestamp,logoff_date timestamp
);-- 登录触发器:用户登录时记录信息
create or replace trigger tr_logon
after logon on database  -- 数据库级事件:登录后
begininsert into log_event (user_name, address, logon_date)values (ora_login_user, ora_client_ip_address, systimestamp);
end tr_logon;

七、模块化管理:程序包

当存储过程和函数越来越多时,用 “程序包” 管理会更清晰 —— 类似将多个工具放进一个 “工具箱”,方便调用和维护。

程序包由两部分组成:

  • 包声明(package):定义对外暴露的存储过程、函数、变量(类似 “接口”)。
  • 包体(package body):实现包声明中定义的逻辑(类似 “实现类”)。

示例:创建管理部门的程序包

plsql

-- 1. 包声明:定义要包含的存储过程
create or replace package my_package asprocedure add_my_dept2(V_deptno number, V_dname varchar2, V_loc varchar2);procedure del_my_dept3(V_deptno number);
end;-- 2. 包体:实现存储过程的逻辑
create or replace package body my_package as-- 实现新增部门procedure add_my_dept2(V_deptno number, V_dname varchar2, V_loc varchar2) isbegininsert into my_dept values(V_deptno, V_dname, V_loc);commit;end add_my_dept2;-- 实现删除部门procedure del_my_dept3(V_deptno number) isbegindelete from my_dept where deptno = V_deptno;commit;end del_my_dept3;
end;

调用时直接通过包名访问:

plsql

exec my_package.add_my_dept2(20, '测试部', '广州');

总结:从入门到熟练的关键

PL/SQL 是 ORACLE 数据库操作的核心工具,掌握它需要:

  1. 理解块的分类(无名块、存储过程、触发器等)的适用场景;
  2. 牢记标识符规则和命名规范,养成良好编码习惯;
  3. 多动手实践:从简单的无名块开始,逐步尝试存储过程、函数和触发器;
  4. 学会用程序包管理代码,提升项目的可维护性。
http://www.dtcms.com/a/338953.html

相关文章:

  • 开通会话内容存档获取聊天记录
  • 机器学习中的「损失函数」:模型优化的核心标尺
  • 源雀SCRM开源版企微客服功能重磅升级
  • Linux 正则表达式
  • 【新启航】航空飞机起落架深孔型腔的内轮廓检测方法探究 - 激光频率梳 3D 轮廓检测
  • JavaScript 性能优化:new Map vs Array.find() 查找速度深度对比
  • 机器翻译60天修炼专栏介绍和目录
  • C语言:字符函数与字符串函数(1)
  • 从 IP编码地址困局到网络优化:VLSM 与 CIDR 如何破解地址浪费与路由难题
  • 使用 Resilience4j 实现 Spring Boot 服务限流:轻量级容错的最佳实践
  • Java算法之排序
  • Bot 流量“假阳性”调优笔记
  • ListBoxes使得在专为灵活性和易用性设计
  • 消费者API
  • 云电脑 vs 传统PC:全面对比3A游戏与AI训练的成本与性能
  • Leetcode 3654. Minimum Sum After Divisible Sum Deletions
  • 【多模态大模型的三化】
  • [PV]AXI R/W/RW带宽计算的tcl脚本
  • AI赋能商业数据分析:从海量数据挖掘到智能决策洞察,激活企业增长新动能
  • Redisson 分布式锁核心机制解析
  • Flink原理与实践:第一章大数据技术概述总结
  • 微软行业案例:英格兰足球超级联赛(Premier League)
  • 丝杆支撑座在自动化生产线中的关键支撑
  • arcgis-提取范围中最大占比面积的信息或唯一值
  • Jenkins服务器SSH公钥配置步骤
  • nodejs koa框架使用
  • 计算机大数据毕业设计推荐:基于Spark的气候疾病传播可视化分析系统【Hadoop、python、spark】
  • 《算法导论》第 30 章:多项式与快速傅里叶变换(FFT)
  • vue3中封装hooks
  • uniapp 应用未安装:软件包与现有软件包存在冲突