在 SQL 存储过程中,“is” 本质是语法关键字,无独立语义,需结合具体语境(如声明变量、判断条件、定义游标等)发挥作用,核心功能是 “辅助构建语法结构,明确代码逻辑关系”。
不同数据库(Oracle、MySQL、SQL Server)中,“is” 的用法高度一致,不存在数据库特异性,这也是理解它的关键 —— 无需区分数据库类型,掌握通用场景即可。
存储过程中 “is” 的 3 大核心应用场景(附实例)
1. 场景 1:存储过程定义时,用于 “声明部分” 的开头(最基础用法)
在 Oracle 存储过程中,“is” 是区分 “存储过程头部(参数定义)” 与 “内部声明部分(变量、游标定义)” 的语法分隔符,对应 MySQL/SQL Server 中的 “as”(两者功能完全一致,仅语法关键字不同)。
(1)语法结构
-- Oracle存储过程定义:is用于参数列表后,声明部分前
CREATE OR REPLACE PROCEDURE 存储过程名(
参数1 数据类型 [IN/OUT], -- 头部:参数定义
参数2 数据类型 [IN/OUT]
) IS -- 关键:用is分隔头部与声明部分
-- 声明部分:定义变量、常量、游标等
变量名 数据类型;
游标名 CURSOR IS ...; -- 此处is也用于游标定义
BEGIN
-- 执行部分:核心业务逻辑
业务代码;
END 存储过程名;
/
(2)实例解析
以 Oracle 中 “查询员工薪资” 的存储过程为例,看 “is” 的作用:
CREATE OR REPLACE PROCEDURE P_QUERY_EMP_SAL(
P_EMP_ID IN NUMBER, -- 输入参数:员工ID
P_EMP_SAL OUT NUMBER -- 输出参数:返回薪资
) IS -- 分隔参数列表与声明部分,表明后续是内部变量/游标定义
V_DEPT_NO NUMBER; -- 声明变量:存储员工部门编号
-- 声明游标:查询指定员工的薪资和部门编号,此处is用于游标定义
CURSOR C_EMP_INFO IS
SELECT SAL, DEPTNO
FROM EMP
WHERE EMPNO = P_EMP_ID;
BEGIN
-- 打开游标并提取数据
OPEN C_EMP_INFO;
FETCH C_EMP_INFO INTO P_EMP_SAL, V_DEPT_NO;
CLOSE C_EMP_INFO;
DBMS_OUTPUT.PUT_LINE('员工部门编号:' || V_DEPT_NO);
EXCEPTION
WHEN NO_DATA_FOUND THEN
P_EMP_SAL := 0;
DBMS_OUTPUT.PUT_LINE('未找到该员工');
END P_QUERY_EMP_SAL;
/
关键说明:
•此处第一个 “is”() IS)的作用是 “告诉数据库:参数列表已定义完成,接下来是存储过程内部的变量、游标等声明”,是语法结构的 “分隔标志”,无实际语义,不能省略;
•若省略 “is”,存储过程会编译报错(如 Oracle 提示 “ORA-00905: 缺失关键字”),因为数据库无法区分 “参数定义” 和 “内部声明” 的边界。
(3)与 MySQL/SQL Server 的对比
MySQL 和 SQL Server 中,用 “as” 替代 “is” 实现相同功能,语法结构一致:
-- MySQL存储过程:用as替代is
CREATE PROCEDURE P_QUERY_EMP_SAL(
IN P_EMP_ID INT,
OUT P_EMP_SAL DECIMAL(10,2)
) AS -- 此处as = Oracle中的is
DECLARE V_DEPT_NO INT; -- 声明变量
BEGIN
SELECT SAL INTO P_EMP_SAL
FROM EMP
WHERE EMPNO = P_EMP_ID;
END;
本质上,“is” 和 “as” 是 “同功能不同关键字”,仅数据库语法约定差异,核心作用都是 “分隔参数与声明部分”。
2. 场景 2:判断 “空值(NULL)” 时,用于 “is null” 或 “is not null”
在存储过程的条件判断(如 if、where 子句)中,“is” 常与 “null” 搭配,构成 “is null”(判断值为空)或 “is not null”(判断值不为空),用于处理 SQL 中的空值逻辑—— 这是 “is” 最常用的功能之一,也是初学者易混淆的点(需注意:不能用 “= null” 判断空值,SQL 语法规定 “null 与任何值比较都为 null”,必须用 “is null”)。
(1)语法结构
-- 1. if条件中判断空值
IF 变量名 IS NULL THEN
处理逻辑; -- 变量为空时执行
END IF;
IF 变量名 IS NOT NULL THEN
处理逻辑; -- 变量不为空时执行
END IF;
-- 2. 查询/更新语句中判断空值
SELECT 列名 INTO 变量名
FROM 表名
WHERE 列名 IS NULL; -- 筛选列值为空的记录
(2)实例解析
在存储过程中 “处理员工奖金发放” 时,用 “is null” 判断奖金是否为空,若为空则默认发放 500 元:
CREATE OR REPLACE PROCEDURE P_CALC_BONUS(
P_EMP_ID IN NUMBER,
P_BONUS OUT NUMBER -- 输出最终奖金
) IS
V_EMP_BONUS NUMBER; -- 存储员工原奖金
BEGIN
-- 查询员工原奖金
SELECT BONUS INTO V_EMP_BONUS
FROM EMP
WHERE EMPNO = P_EMP_ID;
-- 判断原奖金是否为空,用is null
IF V_EMP_BONUS IS NULL THEN
P_BONUS := 500; -- 空值时默认发500
DBMS_OUTPUT.PUT_LINE('原奖金为空,默认发放500元');
ELSE
P_BONUS := V_EMP_BONUS; -- 不为空则用原奖金
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
P_BONUS := 0;
DBMS_OUTPUT.PUT_LINE('员工不存在');
END P_CALC_BONUS;
/
关键说明:
•若此处误写为 “IF V_EMP_BONUS = NULL THEN”,存储过程会永远执行 “else” 分支,因为 “null = null” 的结果是 “null”(不成立),SQL 语法强制要求用 “is null” 判断空值;
•“is not null” 的用法类似,例如 “IF P_EMP_ID IS NOT NULL THEN”(判断输入参数不为空,再执行查询),避免因参数为空导致的查询错误。
3. 场景 3:定义游标时,用于 “指定游标对应的查询语句”
在存储过程中声明 “显式游标”(用于遍历查询结果集)时,“is” 是游标定义的固定语法关键字,作用是 “将游标与具体的查询语句绑定”,即 “明确该游标对应哪条 SQL 查询的结果”。
(1)语法结构
-- 存储过程中声明显式游标
CURSOR 游标名 IS
SELECT 列名1, 列名2 ...
FROM 表名
WHERE 条件; -- 游标对应的查询语句
(2)实例解析
在 “批量更新员工薪资” 的存储过程中,用游标遍历 “部门编号为 30” 的员工,此处 “is” 用于绑定游标与查询语句:
CREATE OR REPLACE PROCEDURE P_UPDATE_EMP_SAL(
P_DEPT_NO IN NUMBER, -- 输入参数:部门编号
P_INCREASE_RATE IN NUMBER -- 输入参数:薪资增长率
) IS
-- 声明游标:绑定“查询指定部门员工”的SQL,is用于关联游标与查询
CURSOR C_EMP_LIST IS
SELECT EMPNO, SAL
FROM EMP
WHERE DEPTNO = P_DEPT_NO;
V_EMP_NO NUMBER; -- 存储游标提取的员工ID
V_EMP_SAL NUMBER; -- 存储游标提取的原薪资
BEGIN
-- 打开游标并循环遍历
OPEN C_EMP_LIST;
LOOP
FETCH C_EMP_LIST INTO V_EMP_NO, V_EMP_SAL;
EXIT WHEN C_EMP_LIST%NOTFOUND; -- 无数据时退出循环
-- 更新薪资:原薪资 * (1 + 增长率)
UPDATE EMP
SET SAL = V_EMP_SAL * (1 + P_INCREASE_RATE)
WHERE EMPNO = V_EMP_NO;
DBMS_OUTPUT.PUT_LINE('员工' || V_EMP_NO || '薪资已更新');
END LOOP;
CLOSE C_EMP_LIST;
COMMIT; -- 提交事务
END P_UPDATE_EMP_SAL;
/
关键说明:
•此处 “CURSOR C_EMP_LIST IS” 中的 “is” 是固定语法,不能替换为 “as” 或省略,作用是 “告诉数据库:C_EMP_LIST 这个游标的结果集,来自后面的 SELECT 语句”;
•游标定义后,需通过 “open→fetch→close” 操作遍历数据,而 “is” 是建立游标与查询语句关联的 “桥梁”,没有 “is”,数据库无法识别游标对应的结果集。
常见误区与注意事项
1. 误区 1:将 “is” 与 “as” 混淆,认为功能不同
在 Oracle 存储过程中,“is” 和 “as” 在 “分隔参数与声明部分” 时功能完全一致,可互换使用,例如:
-- 用as替代is,语法完全合法
CREATE OR REPLACE PROCEDURE P_TEST(
P_PARAM IN NUMBER
) AS -- 此处as = is
V_VAR NUMBER;
BEGIN
V_VAR := P_PARAM;
END P_TEST;
/
唯一区别是 “习惯用法”:Oracle 开发者更常用 “is” 定义存储过程,用 “as” 定义函数(FUNCTION),但语法层面两者无差异。
2. 误区 2:用 “= null” 替代 “is null” 判断空值
这是初学者最易犯的错误,需牢记:SQL 中 “null” 是 “未知值”,不能用 “=、!=” 等比较运算符判断,必须用 “is null” 或 “is not null”。
例如,以下代码会导致逻辑错误:
-- 错误写法:用= null判断空值
IF V_EMP_SAL = NULL THEN
P_BONUS := 500;
END IF;
正确写法:
-- 正确写法:用is null
IF V_EMP_SAL IS NULL THEN
P_BONUS := 500;
END IF;
3. 注意事项:不同数据库中 “is” 的语法一致性
无论是 Oracle、MySQL、SQL Server,还是 PostgreSQL,“is” 在 “判断空值(is null)” 和 “定义游标(cursor ... is)” 时的用法完全一致,仅在 “存储过程头部分隔” 时,MySQL/SQL Server 用 “as”,Oracle 用 “is”,但核心逻辑无差异,无需重复学习不同数据库的用法。
总结:存储过程中 “is” 的核心作用速记
应用场景 作用描述 关键示例
存储过程定义分隔 分隔参数列表与内部声明部分,语法标志 ) IS(Oracle)
判断空值 与 null 搭配,判断值为空或不为空 IS NULL、IS NOT NULL
显式游标定义 绑定游标与查询语句,明确游标结果集来源 CURSOR 游标名 IS SELECT ...
简言之,存储过程中的 “is” 要么是 “语法结构的分隔符”(如定义存储过程、游标),要么是 “空值判断的关键字”(如 is null),无其他独立含义。掌握这 3 个场景,就能轻松理解和使用 “is”,避免语法错误。