当前位置: 首页 > 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.lryc.cn/news/625335.html

相关文章:

  • 摄像头模块在运动相机中的应用
  • arcgis-提取范围中最大占比面积的信息或唯一值
  • 面试问题详解四:Qt 多线程与信号槽机制
  • Day09 Go语言深入学习(1)
  • 8.19作业
  • 工业相机基本知识解读:像元、帧率、数据接口等
  • 视觉采集模块的用法
  • HTML应用指南:利用GET请求获取全国新荣记门店位置信息
  • BEV:隐式相机视角转换-----BEVFormer
  • C#/.NET/.NET Core技术前沿周刊 | 第 50 期(2025年8.11-8.17)
  • 【leetcode 3】最长连续序列 (Longest Consecutive Sequence) - 解题思路 + Golang实现
  • Selenium使用指南
  • Ubuntu conda虚拟环境下pip换源
  • jsPDF 不同屏幕尺寸 生成的pdf不一致,怎么解决
  • 软件测试-Selenium学习笔记
  • LeetCode 134.加油站:贪心策略下的环形路线可行性判断
  • 【基础-判断】用户在长视频、短视频、直播、通话、会议、拍摄类应用等场景下,可以采用悬停适配在折叠屏半折态时,上屏进行浏览下屏进行交互操作
  • 技术分享:跨域问题的由来与解决
  • WebSocket的连接原理
  • Ansible 配置并行 - 项目管理笔记
  • Go 并发入门:从 goroutine 到 worker pool
  • 边缘智能体:Go编译在医疗IoT设备端运行轻量AI模型(中)
  • CentOS 8开发测试环境:直接安装还是Docker更优?
  • 半导体笔记<01-半导体中的数据>
  • C5.5:VDB及后面的电路讨论
  • C++STL-vector底层实现
  • [日常学习] -2025-8-18- 页面元类和装饰器工厂
  • VSCode 从安装到精通:下载安装与快捷键全指南
  • LINUX 软件编程 -- 线程
  • WebPack》》Loader原理、分类