知识库✳

教程与手册

全部教程
  1. 01Oracle 函数手册
  2. 02性能优化手册
  3. 03Linux Shell
  4. 04Oracle 学习与演练
  5. 05网络基础学习
  6. 06数据治理与管理
返回个人网站
甲Oracle 学习教程从 SQL 到 PL/SQL 与运维
首页课程目录搜索演练场
知识库

已完成 0 / 22 章

模块一 · 入门与准备

  • 01Oracle 数据库体系结构
  • 02环境安装与连接方式
  • 03SQL*Plus 与常用工具

模块二 · SQL 查询基础

  • 04SELECT 查询基础
  • 05过滤与排序
  • 06单行函数
  • 07多表连接
  • 08分组聚合与 HAVING
  • 09子查询

模块三 · 数据与对象

  • 10DML 与事务控制
  • 11表与数据类型
  • 12约束
  • 13索引与执行计划
  • 14视图、序列与同义词

模块四 · PL/SQL 编程

  • 15PL/SQL 块与变量
  • 16流程控制与游标
  • 17存储过程与函数
  • 18触发器
  • 19异常处理

模块五 · 运维与进阶

  • 20用户与权限管理
  • 21表空间与存储管理
  • 22备份与恢复
❖

Oracle 学习教程

返回个人网站知识库

示例代码基于 Oracle AI Database 26ai / 23ai,查询示例使用官方 HR 示例方案。

以 Next.js 16 · Tailwind CSS v4 · HeroUI v3 装帧

15
  1. 首页
  2. 课程目录
  3. PL/SQL 块与变量

第 15 章◆进阶◆建议 45 分钟◆模块四 · PL/SQL 编程

PL/SQL 块与变量

从匿名块开始,理解 PL/SQL 的结构、变量声明与 %TYPE/%ROWTYPE 的用法。

学完这一章,你应该能

  • 写出结构完整的匿名块
  • 会用 %TYPE 与 %ROWTYPE 避免类型不同步
  • 掌握 DBMS_OUTPUT 调试输出
  • 分清替换变量与绑定变量

15.1匿名块结构

  • DECLARE 段可选;BEGIN...END 必须存在
  • 每条语句以分号结束,END 后面也要分号
  • PL/SQL 里的 SELECT 必须用 INTO 接收结果,且只能返回一行
  • SET SERVEROUTPUT ON 不执行的话,DBMS_OUTPUT 的内容看不到
最小可运行块
SET SERVEROUTPUT ON

DECLARE
  v_name  VARCHAR2(50);
  v_count NUMBER := 0;          -- 声明时可直接初始化
  c_pi    CONSTANT NUMBER := 3.14159;   -- 常量必须初始化
BEGIN
  SELECT COUNT(*) INTO v_count FROM employees;
  DBMS_OUTPUT.PUT_LINE('员工总数: ' || v_count);
EXCEPTION
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE('出错: ' || SQLERRM);
END;
/

结尾的 / 是执行匿名块的必需符号,不是 SQL 的一部分。

15.2锚定类型:%TYPE 与 %ROWTYPE

硬编码类型(写成 VARCHAR2(25))在表结构变更后会失效。用 %TYPE 让变量自动跟随列类型,用 %ROWTYPE 直接跟随整行结构,这是 PL/SQL 的惯用做法。

锚定类型示例
DECLARE
  v_last_name  employees.last_name%TYPE;   -- 跟随列类型
  v_emp        employees%ROWTYPE;           -- 跟随整行
BEGIN
  SELECT last_name INTO v_last_name
  FROM   employees WHERE employee_id = 100;

  SELECT * INTO v_emp
  FROM   employees WHERE employee_id = 100;

  DBMS_OUTPUT.PUT_LINE(v_last_name || ' / ' || v_emp.salary);
END;
/

只作示例阅读:5 行写入限制下不执行任意 PL/SQL、循环写入或动态 SQL;只开放字面量 DBMS_OUTPUT 打印。请在独立学习数据库中练习。

15.3替换变量 vs 绑定变量

  • 替换变量是客户端文本替换,等于每次都是一条新 SQL(硬解析)
  • 绑定变量让相同结构的 SQL 复用游标,减少硬解析,是性能关键
  • 应用开发中一律用绑定变量,绝不用字符串拼接把值塞进 SQL(还能防注入)
两者不要混淆
-- 替换变量 &x:SQL*Plus 层做文本替换,编译期生效
-- 执行时 SQL*Plus 会提示你现场输入 emp_id 的值,
-- 属于交互式用法,不能放进脚本批量跑
SELECT * FROM employees WHERE employee_id = &emp_id;

-- 绑定变量 :x:值在运行期传入,SQL 可以复用解析结果
VARIABLE b_emp_id NUMBER
EXEC :b_emp_id := 100
SELECT last_name FROM employees WHERE employee_id = :b_emp_id;
PRINT b_emp_id

练习

3 题 · 先自己写,再展开对照

参考答案

行,但很脆。硬编码的类型在表结构变更后会失效或悄悄截断。

%TYPE 跟随某一列的类型:
  v_last_name employees.last_name%TYPE;

%ROWTYPE 跟随整行结构:
  v_emp employees%ROWTYPE;

好处是表结构改了,PL/SQL 代码不用同步改,也不会出现
「列加长了但变量还是旧长度」这类隐蔽问题。这是 PL/SQL 的惯用做法。

自评要点

  • 说清 %TYPE 与 %ROWTYPE 各自跟随什么
  • 指出硬编码类型的脆性

参考答案

替换变量 &x 是 SQL*Plus 客户端层面的文本替换:它把文本直接插入
语句,所以每次值不同就等于一条全新的 SQL,需要重新硬解析。

绑定变量 :x 是运行期传值,SQL 文本结构不变,可以复用已解析的游标,
大幅减少硬解析开销。

安全上更关键:用字符串拼接把用户输入塞进 SQL 会造成 SQL 注入,
绑定变量天然规避这个问题。所以应用代码里应该一律用绑定变量。

自评要点

  • 文本替换 vs 运行期传值
  • 提到硬解析开销
  • 提到 SQL 注入

参考答案

因为没打开输出缓冲。执行前必须先:

SET SERVEROUTPUT ON

另外要确认:缓冲有大小限制(SET SERVEROUTPUT ON SIZE 1000000 可调大),
输出过长会被截断;而且它是给人看的调试手段,
不要在有性能要求的批量作业里大量使用。

自评要点

  • SET SERVEROUTPUT ON
  • 知道输出有缓冲上限
← 上一章

视图、序列与同义词

下一章 →

流程控制与游标