PL/SQL 命令可以分为两大类:

- SQL 命令:用于操作数据库中的数据(如
SELECT,INSERT,UPDATE,DELETE,COMMIT,ROLLBACK),这些是 PL/SQL 程序中最常用的命令。 - PL/SQL 语言结构命令:用于定义程序结构、控制流程和处理异常,这些是 PL/SQL 特有的。
下面我将详细列出这两类中的核心命令和结构,并提供示例。
核心 SQL 命令(在 PL/SQL 中使用)
这些命令是操作数据的基础,通常在 PL/SQL 的 DML(数据操作语言)块或 SQL 游标中使用。
| 命令 | 描述 | 示例 |
|---|---|---|
SELECT ... INTO |
从数据库中查询一行数据,并将结果存入变量。必须确保查询返回且仅返回一行,否则会抛出异常。 | SELECT ename, sal INTO v_ename, v_sal FROM emp WHERE empno = 7788; |
INSERT |
向表中插入一行或多行数据。 | INSERT INTO emp (empno, ename) VALUES (9999, 'TEST_USER'); |
UPDATE |
更新表中一行或多行的数据。 | UPDATE emp SET sal = sal * 1.1 WHERE deptno = 10; |
DELETE |
从表中删除一行或多行数据。 | DELETE FROM emp WHERE hire_date < TO_DATE('2000-01-01', 'YYYY-MM-DD'); |
COMMIT |
提交当前事务,将所有未保存的更改永久保存到数据库。 | COMMIT; |
ROLLBACK |
回滚当前事务,撤销自上一个 COMMIT 或 ROLLBACK 以来所做的所有更改。 |
ROLLBACK; |
SAVEPOINT |
在事务中设置一个保存点,可以允许事务回滚到这个点,而不是全部回滚。 | SAVEPOINT before_update;ROLLBACK TO before_update; |
PL/SQL 语言结构命令
这些是构建 PL/SQL 程序块的关键元素。
块结构
PL/SQL 程序由块组成,块是基本单元。

DECLARE
-- 声明部分: 定义变量、游标、异常等
v_name VARCHAR2(50);
BEGIN
-- 执行部分: 包含 SQL 语句和 PL/SQL 逻辑
v_name := 'PL/SQL Block';
DBMS_OUTPUT.PUT_LINE('Hello from ' || v_name);
EXCEPTION
-- 异常处理部分: 处理执行过程中可能出现的错误
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('An error occurred: ' || SQLERRM);
END;
/
变量声明与赋值
| 结构 | 描述 | 示例 |
|---|---|---|
DECLARE |
关键字,用于声明变量的开始。 | DECLARE ... |
variable_name datatype [CONSTRAINT] [DEFAULT value]; |
声明一个变量。 | v_empno NUMBER(5) PRIMARY KEY := 7788;v_bonus NUMBER(10,2) DEFAULT 0; |
| 赋值运算符,用于给变量赋值。 | v_total := v_price * v_quantity; |
|
& |
替换变量,用于在运行时接收用户输入。 | SELECT * FROM emp WHERE deptno = &p_deptno; |
控流结构
条件语句
| 结构 | 描述 | 示例 |
|---|---|---|
IF ... THEN ... END IF; |
简单的 IF 语句。 | IF v_sal > 5000 THENDBMS_OUTPUT.PUT_LINE('High Salary');END IF; |
IF ... THEN ... ELSE ... END IF; |
IF-ELSE 语句。 | IF v_deptno = 10 THENDBMS_OUTPUT.PUT_LINE('Accounting');ELSEDBMS_OUTPUT.PUT_LINE('Other Dept');END IF; |
IF ... THEN ... ELSIF ... ELSE ... END IF; |
多重条件判断。 | IF v_sal > 10000 THENv_grade := 'A';ELSIF v_sal > 5000 THENv_grade := 'B';ELSEv_grade := 'C';END IF; |
循环语句
| 结构 | 描述 | 示例 |
|---|---|---|
LOOP ... EXIT WHEN ... END LOOP; |
基本循环,需要手动指定退出条件。 | v_counter := 1;LOOPDBMS_OUTPUT.PUT_LINE(v_counter);v_counter := v_counter + 1;EXIT WHEN v_counter > 5;END LOOP; |
WHILE ... LOOP ... END LOOP; |
当条件为真时,循环执行。 | v_counter := 1;WHILE v_counter <= 5 LOOPDBMS_OUTPUT.PUT_LINE(v_counter);v_counter := v_counter + 1;END LOOP; |
FOR counter IN [REVERSE] start..end LOOP ... END LOOP; |
固定次数的循环,自动声明和递增/递减计数器。 | FOR i IN 1..5 LOOPDBMS_OUTPUT.PUT_LINE(i);END LOOP;FOR i IN REVERSE 1..5 LOOPDBMS_OUTPUT.PUT_LINE(i);END LOOP; |
异常处理
| 结构 | 描述 | 示例 |
|---|---|---|
DECLARE ... BEGIN ... EXCEPTION ... END; |
完整的异常处理块结构。 | 见上面的块结构示例。 |
WHEN exception_name THEN |
捕获特定的预定义或自定义异常。 | WHEN NO_DATA_FOUND THENDBMS_OUTPUT.PUT_LINE('No employee found!');WHEN TOO_MANY_ROWS THENDBMS_OUTPUT.PUT_LINE('Query returned multiple rows!');WHEN OTHERS THENDBMS_OUTPUT.PUT_LINE('Error: ' || SQLERRM); |
RAISE_APPLICATION_ERROR(error_number, message); |
在代码中主动抛出一个自定义错误,中止当前执行的块。 | IF v_sal < 0 THENRAISE_APPLICATION_ERROR(-20001, 'Salary cannot be negative!');END IF; |
游标
游标用于处理多行 SELECT 语句的结果集。
| 结构 | 描述 | 示例 |
|---|---|---|
CURSOR cursor_name IS query; |
声明一个游标。 | CURSOR c_emp IS SELECT ename, sal FROM emp WHERE deptno = 20; |
OPEN cursor_name; |
打开游标,执行查询并填充结果集。 | OPEN c_emp; |
FETCH cursor_name INTO variable_list; |
从游标中提取一行数据到变量中。 | FETCH c_emp INTO v_ename, v_sal; |
CLOSE cursor_name; |
关闭游标,释放相关资源。 | CLOSE c_emp; |
FOR record IN cursor_name LOOP ... END LOOP; |
隐式游标循环,自动处理打开、获取和关闭。 | FOR r_emp IN c_emp LOOPDBMS_OUTPUT.PUT_LINE('Name: ' || r_emp.ename || ', Salary: ' || r_emp.sal);END LOOP; |
过程与函数
| 结构 | 描述 | 示例 |
|---|---|---|
CREATE OR REPLACE PROCEDURE procedure_name (parameters) IS ... BEGIN ... END; |
创建或替换一个存储过程,执行操作但不返回值。 | CREATE OR REPLACE PROCEDURE give_raise (p_empno IN NUMBER, p_raise_pct IN NUMBER) ISBEGINUPDATE emp SET sal = sal * (1 + p_raise_pct / 100) WHERE empno = p_empno;COMMIT;END give_raise; |
CREATE OR REPLACE FUNCTION function_name (parameters) RETURN datatype IS ... BEGIN ... RETURN value; END; |
创建或替换一个存储函数,执行操作并返回一个值。 | CREATE OR REPLACE FUNCTION get_employee_name (p_empno IN NUMBER) RETURN VARCHAR2 ISv_name emp.ename%TYPE;BEGINSELECT ename INTO v_name FROM emp WHERE empno = p_empno;RETURN v_name;END get_employee_name; |
EXECUTE procedure_name; 或 CALL procedure_name(); |
调用一个存储过程。 | EXECUTE give_raise(7788, 10); |
variable_name := function_name(parameters); |
调用一个存储函数。 | v_name := get_employee_name(7788); |
包
包是相关的过程、函数、变量、游标和异常的命名容器,提供了模块化和数据隐藏。
| 结构 | 描述 | 示例 |
|---|---|---|
CREATE OR REPLACE PACKAGE package_name IS-- 公共声明(API)END package_name; |
创建包规范,只包含签名(名称、参数、返回类型),不包含实现。 | CREATE OR REPLACE PACKAGE emp_api ISPROCEDURE give_raise (p_empno IN NUMBER, p_raise_pct IN NUMBER);FUNCTION get_employee_name (p_empno IN NUMBER) RETURN VARCHAR2;END emp_api; |
CREATE OR REPLACE PACKAGE BODY package_name IS-- 私有声明和实现END package_name; |
创建包体,包含规范中声明的所有子程序的实现。 | CREATE OR REPLACE PACKAGE BODY emp_api IS-- give_raise 的实现PROCEDURE give_raise (...) IS ...-- get_employee_name 的实现FUNCTION get_employee_name (...) RETURN VARCHAR2 IS ...END emp_api; |
常用的内置包和命令
这些是 PL/SQL 开发中非常实用的工具。
| 包/命令 | 描述 | 示例 |
|---|---|---|
DBMS_OUTPUT.PUT_LINE(text); |
将文本输出到 SQL*Plus 或 SQL Developer 的 "DBMS Output" 窗口,这是调试最常用的方法。 | DBMS_OUTPUT.PUT_LINE('Hello, PL/SQL!'); |
DBMS_OUTPUT.ENABLE(buffer_size); |
启用 DBMS_OUTPUT,在 SQL Developer/SQL*Plus 中,通常需要先运行此命令。 |
BEGINDBMS_OUTPUT.PUT_LINE('This will be printed.');END;-- 在 SQL*Plus 中可能需要先执行 SET SERVEROUTPUT ON |
RAISE exception_name; |
显式地触发一个预定义的异常。 | IF v_sal < 0 THENRAISE VALUE_ERROR;END IF; |
希望这份详细的清单能帮助你更好地理解和使用 PL/SQL!

