MySQL存储过程传参(IN/OUT/INOUT)与流程控制实战

凌晨两点半
凌晨两点半
发布时间:2026-10-15| 2人浏览过
原创

本文将深入解析MySQL存储过程的参数传递机制(IN、OUT、INOUT)以及核心的流程控制语句(IF判断、CASE分支、循环结构),通过具体的代码示例和截图演示,帮助用户理解如何在数据库中封装复杂的业务逻辑。

一、存储过程传参:IN(输入参数)

IN 表示传入的参数。在调用存储过程时,可以传入常量数值或变量。需要注意的是,即使在存储过程内部修改了 IN 参数变量的值,也不会影响外部传入的原始变量,其作用域仅限于存储过程内部。

第1步:基础传参查询

目的:根据传入的员工编号,查询对应的员工信息。

use test_procedure;
-- 定义带有in参数的存储过程
delimiter $$
create procedure proc6(in in_empno int)
begin
	select * from emp where emp.empno = in_empno;
end $$
delimiter ;

-- 调用测试
CALL proc6(1001); 

第2步:多条件组合查询

目的:根据部门名称和薪资阈值,查询指定部门且薪资高于设定值的员工。

delimiter $$
create procedure proc7(in in_dname char(50),in in_sal int)
begin
	SELECT * FROM dept,emp 
	WHERE dept.deptno = emp.deptno 
	  AND (dept.dname=in_dname) 
	  AND (in_sal < emp.sal);
end $$
delimiter ;

-- 调用:查询学工部中薪资大于20000的员工
CALL proc7('学工部', 20000); 

二、存储过程传参:OUT(输出参数)

OUT 参数用于从存储过程内部向外部返回结果。调用存储过程后,外部变量将接收到存储过程执行结束后的最终值。通常配合用户变量(如 @var_name)使用。

第3步:返回单个字段

目的:传入员工编号,返回该员工的姓名。

delimiter $$
create procedure proc8(in in_empno int, out out_ename varchar(50))
begin
	-- 将查询结果赋值给out参数
	SELECT ename INTO out_ename FROM emp WHERE emp.empno = in_empno;
end $$
delimiter ;

-- 调用并查看结果
CALL proc8(1001, @o_ename); -- 执行无直接输出
SELECT @o_ename; 

第4步:返回多个字段

目的:传入员工编号,同时返回员工姓名和薪资。

delimiter $$
create procedure proc9(in in_empno int, out out_ename varchar(50), out out_sal int)
begin
	SELECT emp.ename, emp.sal INTO out_ename, out_sal 
	FROM emp WHERE emp.empno = in_empno;
end $$
delimiter ;

CALL proc9(1001, @o_ename, @o_sal);
SELECT @o_ename, @o_sal; 

三、存储过程传参:INOUT(双向参数)

INOUT 结合了 IN 和 OUT 的特性。它允许将外部变量的值传入存储过程,并在过程内部修改该变量,修改后的值在存储过程结束后会回传给外部变量。

第5步:数值计算与回传

目的:传入一个数字,将其乘以10后返回。

delimiter $$
create procedure proc10(inout num int)
begin
	SET num = num * 10;
end $$
delimiter ;

-- 注意:INOUT参数必须使用用户变量传递
SET @inout_num = 10;
CALL proc10(@inout_num);
SELECT @inout_num; 

第6步:字符串拼接与数值运算

目的:传入员工姓名和月薪,返回“部门号_姓名”格式的名字,并将月薪转换为年薪。

delimiter $$
create procedure proc11(inout inout_ename varchar(50), inout inout_sal int)
begin
	-- 获取部门号并拼接名字
	SELECT concat_ws('_', emp.deptno, emp.ename) INTO inout_ename
	FROM emp WHERE emp.ename = inout_ename;
	
	-- 计算年薪
	SET inout_sal = inout_sal * 12;
end $$
delimiter ;

SET @ino_ename = '关羽';
SET @ino_sal = 20000;
CALL proc11(@ino_ename, @ino_sal);
SELECT @ino_ename, @ino_sal; 

四、流程控制:IF判断语句

IF 语句类似于编程语言中的 if-elseif-else 结构,根据条件的真假执行不同的SQL块。

第7步:成绩等级评定

目的:根据分数返回对应的等级(不及格、及格、良好、优秀)。

delimiter $$
create procedure proc12(in in_score int)
begin
	IF in_score < 60 THEN
		SELECT '不及格';
	ELSEIF in_score <= 80 THEN
		SELECT '及格';
	ELSEIF in_score <= 90 THEN
		SELECT '良好';
	ELSEIF in_score <= 100 THEN
		SELECT '优秀';
	ELSE
		SELECT '成绩错误';
	END IF;
end $$
delimiter ;

CALL proc12(77); 

第8步:薪资分类与变量处理

目的:根据员工姓名获取薪资,并划分为试用期、转正期或元老级。演示了局部变量(DECLARE)和用户变量(@)的不同处理方式。

-- 方法一:使用局部变量 DECLARE
delimiter $$
create procedure proc13(in in_ename varchar(50))
begin
	declare de_sal decimal(7,2);
	declare de_result varchar(50);
	
	-- 查询薪资到局部变量
	SELECT emp.sal INTO de_sal FROM emp WHERE emp.ename = in_ename;
	
	IF de_sal < 10000 THEN
		SET de_result='试用薪资';
	ELSEIF de_sal < 20000 THEN
		SET de_result='转正薪资';
	ELSE
		SET de_result='元老薪资';
	END IF;
	SELECT de_result; -- 返回分类结果
end $$
delimiter ;

CALL proc13('关羽');

-- 方法二:使用用户变量(无需DECLARE声明)
delimiter $$
create procedure proc14(in in_ename varchar(50))
begin
	declare de_sal decimal(7,2);
	
	-- 直接查询到用户变量
	SELECT emp.sal INTO @de_sal FROM emp WHERE emp.ename = in_ename;
	
	IF @de_sal < 10000 THEN
		SET @de_result='试用薪资';
	ELSEIF @de_sal < 20000 THEN
		SET @de_result='转正薪资';
	ELSE
		SET @de_result='元老薪资';
	END IF;
end $$
delimiter ;

CALL proc14('关羽');
SELECT @de_sal, @de_result; 

五、流程控制:CASE分支

CASE 语句类似于编程语言中的 switch-case,适用于多值分支判断。支持两种语法格式。

第9步:支付方式转换

目的:根据数字类型返回对应的支付渠道名称。

-- 格式一:CASE expression WHEN value THEN ...
delimiter $$
create procedure proc16(in in_type int)
begin
	CASE in_type
		WHEN 1 THEN SELECT '微信支付';
		WHEN 2 THEN SELECT '支付宝支付';
		WHEN 3 THEN SELECT '银行卡支付';
		WHEN 4 THEN SELECT '其他方式支付';
	END CASE;
end $$
delimiter ;

CALL proc16(2);

-- 格式二:CASE WHEN condition THEN ...
delimiter $$
create procedure proc17(in in_type int)
begin
	CASE 
		WHEN in_type=1 THEN SELECT '微信支付';
		WHEN in_type=2 THEN SELECT '支付宝支付';
		WHEN in_type=3 THEN SELECT '银行卡支付';
		WHEN in_type=4 THEN SELECT '其他方式支付';
	END CASE;
end $$
delimiter ;

CALL proc17(4); 

六、流程控制:循环结构

循环允许重复执行一段代码,直到满足特定条件。MySQL主要支持 WHILE、REPEAT 和 LOOP 三种循环,并使用 LEAVE(跳出循环)和 ITERATE(继续下一次)进行控制。

第10步:WHILE循环(先判断后执行)

目的:向表中插入数据,演示如何使用标签(Label)配合 LEAVE 提前终止循环。

注意:使用 LEAVE 或 ITERATE 时必须为循环定义标签。

delimiter $$
create procedure proc18(in in_count int)
begin
	declare i int default 1;
	
	label: WHILE i <= in_count DO
		INSERT INTO user(id, name, password) VALUES(i, CONCAT('user-', i), 123456);
		SET i = i + 1;
		-- 当i等于5时跳出循环
		IF i = 5 THEN LEAVE label;
		END IF;
	END WHILE label;
end $$
delimiter ;

CALL proc18(10); 

第11步:REPEAT循环(先执行后判断)

目的:实现类似功能,但语法结构不同,它在循环末尾判断 UNTIL 条件。

TRUNCATE TABLE user;

delimiter $$
create procedure proc20(in in_count int)
begin
	declare i int default 1;
	
	a: REPEAT 
		INSERT INTO user(id, name, password) VALUES(i, CONCAT('user-', i), 123456);
		SET i = i + 1;
		UNTIL i > in_count 
	END REPEAT a;
end $$
delimiter ;

CALL proc20(10); 

第12步:LOOP循环(需手动退出)

说明:LOOP 本身没有内部终止条件,通常需要结合 IF ... THEN LEAVE 来实现退出,这与 REPEAT 的 UNTIL 不同。

以上就是MySQL存储过程传参及流程控制的详细内容,更多关于MySQL存储过程进阶用法的资料请关注本站其它相关文章!

免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。

Python 相关产品和应用

全部下载
Selenium

Selenium

4.51.0 · Windows

用于浏览器自动化和 Web 测试的 Python 工具。

scikit-learn

scikit-learn

1.9.1 · Windows

常用 Python 机器学习算法与模型评估工具库。

Black

Black

26.10.1 · Windows

强调一致性的 Python 自动代码格式化工具。

Ruff

Ruff

0.17.1 · macOS

由 Rust 编写的高速 Python 代码检查和格式化工具。

pytest

pytest

9.1.1 · Windows

简洁而强大的 Python 自动化测试框架。

FastAPI

FastAPI

0.146.0 · Windows

高性能 Python API 框架,支持类型提示和自动接口文档。

Flask

Flask

3.1.3 · Windows

轻量灵活的 Python Web 应用框架。

Django

Django

6.1.2 · Windows

成熟的 Python Web 框架,适合构建内容站点和业务系统。

Spyder

Spyder

6.1.7 · Windows

面向科学计算与数据分析的 Python 集成开发环境。

SciPy

SciPy

1.18.1 · Windows

面向科学、工程和技术计算的 Python 算法库。