为何pymysql cursor.execute()执行后得到不同结果?
解决Flask+MySQL中cursor.execute()结果不一致的问题
我来帮你捋捋这个cursor.execute()结果不一致的问题,结合你用的Flask 0.12.2和Python 3.6.2版本,大概率是这几个常见坑导致的,一个个来排查:
1. 游标类型不匹配导致返回格式异常
flaskext.mysql默认用的是普通游标,查询返回的是元组列表,如果你期望的是字典格式(键对应字段名),就会觉得“结果不对”。解决方法是指定DictCursor:
from pymysql.cursors import DictCursor # 建立连接时指定游标类型 con = mysql.connect(cursorclass=DictCursor) cursor = con.cursor()
这样执行fetchall()后,返回的是字典列表,和你预期的字段对应关系一致,不会出现“结果结构不对”的错觉。
2. 事务未提交导致数据不一致
如果你的操作涉及增删改,却没提交事务,同一个连接里的查询可能看不到最新修改,不同连接之间的查询结果也会有差异。一定要记得在写入操作后提交:
cursor.execute("INSERT INTO your_table (col1) VALUES (%s)", ("value1",)) con.commit() # 关键步骤,别漏!
要是你做的是只读查询,可以直接开启自动提交,避免事务隔离级别带来的影响:
con.autocommit(True)
3. 游标重复使用未重置导致结果混乱
同一个游标如果多次执行查询,但没把上一次的结果读完,后续的execute结果会和预期不符。建议每次查询用新游标,用完就关闭:
# 每次查询都初始化新游标 cursor = con.cursor() cursor.execute("SELECT * FROM your_table") result = cursor.fetchall() cursor.close() # 用完就关,避免残留数据干扰
4. SQL语句参数化错误导致查询结果异常
如果你用字符串拼接写SQL,很容易因为特殊字符、参数格式问题导致查询结果不符合预期,还会有SQL注入风险。一定要用参数化查询:
# 错误示例:字符串拼接,容易出问题 cursor.execute(f"SELECT * FROM users WHERE id = {user_id}") # 正确示例:参数化,安全又可靠 cursor.execute("SELECT * FROM users WHERE id = %s", (user_id,))
完整示例代码
把上面的注意点整合起来,给你一个可参考的完整实现:
from flask import Flask, jsonify from flaskext.mysql import MySQL from pymysql.cursors import DictCursor app = Flask(__name__) # 数据库配置 app.config['MYSQL_DATABASE_PORT'] = 3306 app.config['MYSQL_DATABASE_USER'] = 'your_username' app.config['MYSQL_DATABASE_PASSWORD'] = 'your_password' app.config['MYSQL_DATABASE_DB'] = 'your_db_name' app.config['MYSQL_DATABASE_HOST'] = 'localhost' mysql = MySQL() mysql.init_app(app) @app.route('/query-data') def query_data(): con = None cursor = None try: # 建立连接并指定字典游标 con = mysql.connect(cursorclass=DictCursor) con.autocommit(True) # 只读场景开启自动提交 cursor = con.cursor() # 参数化查询示例 cursor.execute("SELECT * FROM users WHERE status = %s", ("active",)) result = cursor.fetchall() return jsonify({"success": True, "data": result}) except Exception as e: return jsonify({"success": False, "error": str(e)}), 500 finally: # 确保资源释放 if cursor: cursor.close() if con: con.close() if __name__ == '__main__': app.run(debug=True)
排查的时候还可以打印cursor.rowcount看看影响的行数,或者直接打印fetchall()的结果,确认是格式问题还是数据本身的问题。
内容的提问来源于stack exchange,提问作者puerdon




