一、参数类型说明
MySQL 存储过程的参数分为 3 类,Python 中传递方式各有不同:
- IN:输入参数(默认),仅从 Python 传入 MySQL,存储过程内只读。
- OUT:输出参数,仅从 MySQL 返回到 Python,需提前定义接收变量。
- INOUT:输入输出参数,既传入值,又返回修改后的值。
二、完整示例代码
先在 MySQL 中创建包含 3 类参数的存储过程,再用 Python 调用:
1. 创建测试存储过程
-- 切换到你的数据库
USE test_db;
-- 存储过程:计算a+b的和(OUT),并将c乘以2返回(INOUT)
DELIMITER //
CREATE PROCEDURE calc_params(
IN a INT, -- 输入参数
OUT sum_ab INT, -- 输出参数
INOUT c INT -- 输入输出参数
)
BEGIN
SET sum_ab = a + b; -- 计算a+b(b是隐式的?修正:补充b参数)
-- 修正:完整定义,添加b参数
-- 重新创建正确的存储过程:
DROP PROCEDURE IF EXISTS calc_params;
CREATE PROCEDURE calc_params(
IN a INT,
IN b INT,
OUT sum_ab INT,
INOUT c INT
)
BEGIN
SET sum_ab = a + b; -- 输出a+b的和
SET c = c * 2; -- 输入输出参数:c乘以2返回
END //
DELIMITER ;
2. Python 传递不同参数的代码
import mysql.connector
from mysql.connector import Error
def call_procedure_with_params():
config = {
'host': 'localhost',
'user': 'root',
'password': '你的密码',
'database': 'test_db',
'charset': 'utf8mb4' # 避免中文乱码
}
connection = None
try:
connection = mysql.connector.connect(**config)
cursor = connection.cursor()
# ========== 1. 定义参数 ==========
# IN参数:直接传值
in_a = 10
in_b = 20
# OUT参数:初始化为None,用于接收返回值
out_sum_ab = None
# INOUT参数:先传初始值,最终接收修改后的值
inout_c = 15 # 初始值15,存储过程会改为30
# ========== 2. 调用存储过程(核心:参数按顺序传入元组) ==========
# 格式:cursor.callproc(存储过程名, (参数1, 参数2, ...))
# 参数顺序必须与存储过程定义的顺序完全一致!
cursor.callproc('calc_params', (in_a, in_b, out_sum_ab, inout_c))
# ========== 3. 获取返回的参数值 ==========
# 方式1:通过 cursor.stored_results()(通用)
for result in cursor.stored_results():
# 输出参数和INOUT参数的结果会存在这里
pass # 无结果集时无需读取,参数已自动更新
# 方式2:直接读取 cursor.outputs(更直观)
# cursor.outputs 是字典,key为参数位置(从0开始),value为返回值
# 位置对应:0→in_a, 1→in_b, 2→out_sum_ab, 3→inout_c
out_sum_ab = cursor.outputs[2] # 获取OUT参数值
inout_c = cursor.outputs[3] # 获取INOUT参数修改后的值
# ========== 4. 打印结果 ==========
print("参数传递结果:")
print(f"IN参数 a = {in_a}, b = {in_b}(传入后未修改)")
print(f"OUT参数 sum_ab(a+b)= {out_sum_ab}")
print(f"INOUT参数 c(初始15→×2)= {inout_c}")
connection.commit()
except Error as e:
print(f"错误:{e}")
if connection:
connection.rollback()
finally:
if connection and connection.is_connected():
cursor.close()
connection.close()
if __name__ == "__main__":
call_procedure_with_params()
三、关键细节解释
1. IN 参数传递(最简单)
- 传递方式:直接传入具体值(int/str/float 等),类型需与 MySQL 存储过程定义的一致。
- 示例:
in_a = 10、in_b = 20,直接放入callproc的参数元组即可。 - 注意:MySQL 的
VARCHAR对应 Python 的str,INT对应int,DATETIME可传字符串(如'2026-01-07')或datetime对象。
2. OUT 参数传递
- 传递方式:必须先定义一个变量(通常初始化为
None),放入参数元组。 - 获取返回值:
- 方式 1:
cursor.outputs[参数位置](推荐,直观),位置从 0 开始计数。 - 方式 2:遍历
cursor.stored_results()(兼容所有版本)。
- 方式 1:
- 注意:OUT 参数本身不接收传入的值,仅用于返回,初始值无意义(
None即可)。
3. INOUT 参数传递
- 传递方式:先传入初始值(如
inout_c = 15),放入参数元组。 - 获取返回值:与 OUT 参数相同,通过
cursor.outputs[位置]获取修改后的值。 - 核心特点:既把初始值传给存储过程,又接收存储过程修改后的值。
4. 特殊场景:传递列表/批量参数
如果需要传递多个值(如 IN (1,2,3)),可通过拼接 SQL 或使用参数化查询:
# 示例:调用存储过程,传入多个ID(IN参数)
def call_procedure_with_list():
config = {...} # 同前
connection = mysql.connector.connect(**config)
cursor = connection.cursor()
# 批量ID参数
ids = [1, 2, 3]
# 方式:将列表转为字符串,作为IN参数传入(需确保无SQL注入风险)
id_str = ','.join(map(str, ids))
# 调用存储过程(假设存储过程接收字符串类型的ID列表)
cursor.callproc('get_users_by_ids', (id_str,))
# 读取结果
for result in cursor.stored_results():
print(result.fetchall())