plsql
plsql(Procedural Language/SQL)是甲骨文公司(Oracle)为其关系型数据库提供的过程化扩展语言,在标准SQL的数据操作能力之上加入了变量声明、条件判断、循环和异常处理等编程要素。它把多条SQL语句组织进以块为单位的程序结构中,使复杂业务逻辑可以在数据库内部完成,减少客户端与服务器之间的数据往返。plsql程序单元可保存在数据库中供应用程序反复调用,是Oracle数据库开发中广泛使用的语言。
定义
plsql是甲骨文公司对SQL关系数据库语言所做的一种过程化扩充,通常写作PL/SQL,全称Procedural Language/SQL[1][2]。它并非要取代SQL,而是在SQL之上增加编程语言的结构特征,使数据操作语句能够被组织进一个过程性单元中,借助分支、循环等机制完成较复杂的计算或业务处理[3]。
从语言性质上说,plsql属于第三代过程化语言,与SQL这种面向集合的第四代语言互为补充:SQL擅长描述“要什么结果”,plsql擅长描述“按什么步骤做”[4]。它被直接内置于Oracle数据库,亦可在甲骨文的部分开发工具中运行[5]。
原理
plsql程序以块为基本单位。一个完整的块由声明部分、可执行部分和异常处理部分构成,其中声明与异常处理可以省略,可执行部分必须存在;块前是否带名称,决定了它是匿名块还是可保存到数据库中的命名块[6]。语句之间以分号分隔,整个块以斜杠结束[4]。
运行时,plsql块交由数据库内部的plsql引擎编译,过程性语句由该引擎自行执行,而块中包含的SQL语句则被转交给SQL引擎处理,因此两种语句分别由不同引擎解析[3]。plsql引擎既可以装在数据库服务器中,也可以装在甲骨文Forms一类应用开发工具中;后者在块内不含SQL语句时可独立完成整个单元的执行。
语言中的控制结构分为3类,分别承担条件选择、循环重复与顺序控制,官方文档将其视为plsql对SQL最重要的扩展。数据声明方面,除标量类型外还提供用于保存表格行的记录、保存同类型元素集合的数组类变量,以及用%TYPE和%ROWTYPE等属性沿用已有列或行类型的能力,列定义变化时引用方的类型会随之调整[5]。
游标用于逐行读取查询结果集。它指向一块保存SQL处理信息的私有区域,通过游标属性可以获取语句已影响的行数等状态[7]。异常处理则由预定义异常、非预定义异常和自定义异常三类构成,未处理的异常会沿调用链向外层传播。
发展历程
plsql最早随1991年的Oracle第6版出现,当时的用途相对有限,不支持创建存储过程,主要用于批量执行查询语句[8]。也有资料把plsql对外的第一个公开定义版本记为1995年[2]。
到Oracle第7版,plsql逐渐成熟,开发者可以自行创建过程与函数,并把它们组织进程序包,触发器与类型的实现也开始依托plsql[8]。Oracle 7.3起引入REF CURSOR类型,使存储过程与函数能够返回结果集[1]。
Oracle第8版引入面向对象的相关特性,使plsql在类型定义上更接近完整的程序设计语言。自Oracle 9i起提供预定义的SYS_REFCURSOR类型,开发者不必再自行声明游标类型[1]。Oracle8i第1版加入原生动态SQL,而Oracle 11g第1版在DBMS_SQL包中新增两个转换函数,使DBMS_SQL游标与REF CURSOR之间可以相互转换[9]。
除此之外,plsql也出现在甲骨文之外的环境中,例如TimesTen内存数据库自11.2.1版起、IBM Db2自9.7版起提供对plsql的支持[2]。
应用
plsql最常见的用途是把业务逻辑写入数据库。存储过程、函数、程序包、类型和触发器都属可持久保存的程序单元,一次编写后可被使用Oracle各类编程接口的应用重复调用[2]。
由于代码保存在数据库内部,解析与执行均在数据库端完成,客户端只需发出调用指令、接收最终结果,中间结果无须在网络上往返,因此在处理大量数据时能明显减少网络传输开销[3]。这一特点使plsql适用于批量数据加工、报表统计、数据校验等场景,也用于在数据表上实现触发式的约束与审计逻辑[8]。
plsql程序可以在多种环境中执行,包括命令行工具与图形化开发工具,也可以由高级语言程序调用。以甲骨文Application Express为例,该平台本身即用plsql编写,其存储过程常以DBMS_SQL游标形式返回结果[9]。当plsql无法直接完成某项操作时,还可以调用外部的C函数或数据库内置Java虚拟机中的方法[8]。
局限
plsql与Oracle数据库高度绑定,可移植性主要体现在不同的Oracle数据库之间,迁移到其他数据库产品时往往需要重写[3]。它与SQL Server的Transact-SQL虽表面相似,实质上差异较大,除了功能集合不同,两者在并发与锁的处理方式上也存在显著区别,代码移植工作量通常不小[1]。
在语言定位上,plsql面向逐条处理的过程化逻辑,而SQL面向集合运算,同类任务用纯SQL往往效率更高,因此实践中通常避免用plsql替代本可由SQL完成的操作。数据定义语句如建表、改表、删表不能在plsql中直接书写,需要借助动态SQL方式执行。
早期版本在动态SQL上也有明显限制。使用原生动态SQL时,必须在编译期知道绑定变量与输出项的个数和类型,若语句要到运行期才能确定,这种写法便难以适用,只能退回DBMS_SQL的程序化接口[9]。此外,DBMS_SQL游标与REF CURSOR原先互不兼容,导致在Application Express与Java客户端之间复用存储过程较为困难,这一问题直到Oracle 11g第1版提供转换函数后才得到缓解[9]。
另外,业务逻辑大量集中在数据库端会使数据库承担较重的计算负担,相关逻辑的版本管理与调试也依赖数据库工具链,这是集中式代码存放方式带来的固有代价[3]。
参见
参考资料
- PL/SQL [引用日期2026-10-29]
- PL/SQL (Computer program language) [引用日期2026-10-29]
- Oracle扩展PL/SQL编程简介 [引用日期2026-10-29]
- Oracle总结PLSQL学习 [引用日期2026-10-29]
- Database PL/SQL Language Reference [引用日期2026-10-29]
- PL/SQL --> 语言基础 [引用日期2026-10-29]
- overview [引用日期2026-10-29]
- The Oracle® Hacker's Handbook: Hacking and Defending Oracle [引用日期2026-10-29]
- More on Oracle Database 11g [引用日期2026-10-29]