MySQLdb / PyMySQL 呼叫含 OUT/INOUT 參數的預存程序時,參數值不會直接回傳於 callproc() 結果中,需額外執行 SELECT @_procname_n 讀取伺服器端的會話變數。本文說明完整操作流程與程式碼範例。
cursor.callproc('proc_name', (arg1, arg2, ...)) 後,MySQL 會將參數存為會話變數:@_proc_name_0, @_proc_name_1...(索引從 0 開始)SELECT @_proc_name_n 取得nextset() 推進(Connector/Python 自動處理,MySQLdb 需手動)import MySQLdb
conn = MySQLdb.connect(host='localhost', user='root', passwd='pass', db='mydb')
cursor = conn.cursor()
# 呼叫含 OUT 參數的預存程序
# DeleteUser(user_id, OUT error_msg)
user_id = 'user123'
out_error = '' # 佔位參數
cursor.callproc("DeleteUser", (user_id, out_error))
# 取得 OUT 參數(第 2 個參數,索引 1)
cursor.execute("SELECT @_DeleteUser_1")
result = cursor.fetchall()
if result and result[0][0]: # 非 NULL 表示有錯誤
print("Not Found:", user_id, "\t", result[0][0])
else:
print("Deleted:", user_id)
# 若有多個 OUT 參數,依序查詢
# cursor.execute("SELECT @_DeleteUser_2")
# cursor.execute("SELECT @_DeleteUser_3")
# result = cursor.fetchall()
cursor.close()
conn.close()
cursor.callproc('程序名', 參數元組)cursor.execute("SELECT @_程序名_索引")fetchall() 或 fetchone() 取得結果(回傳為 tuple,取 [0][0] 為實際值)參數索引從 0 開始: 第 1 個參數對應
@_proc_0,第 2 個對應@_proc_1,以此類推。
僅支援 MySQL 5.0+: 預存程序功能需 MySQL 5.0 以上版本。
PEP 249 差異: 標準規定 OUT 參數應直接回傳於 callproc 結果,但 MySQL 因協定限制無法一致實現,故需額外 SELECT。
def call_proc_with_out(cursor, proc_name, args, out_indices):
"""
args: 完整參數列表(含 OUT 佔位)
out_indices: 需取回的 OUT 參數索引列表,如 [1, 2]
回傳: (結果列表, out參數字典)
"""
cursor.callproc(proc_name, args)
out_values = {}
for idx in out_indices:
cursor.execute(f"SELECT @_{proc_name}_{idx}")
row = cursor.fetchone()
out_values[idx] = row[0] if row else None
# 取得結果集(如有)
results = []
for result_cursor in cursor.stored_results():
results.extend(result_cursor.fetchall())
return results, out_values
# 使用範例
results, outs = call_proc_with_out(cursor, 'DeleteUser', ('user123', '', ''), [1, 2])
print("OUT參數:", outs)
掌握此模式,即可在 Python 中完整處理 MySQL 預存程序的輸入輸出參數與結果集。