【python】cursor.fetchall()操作后导致的No result set to fetch from

本文介绍了一个Python脚本,该脚本用于在MySQL数据库中实现账户间的转账功能。文章详细展示了脚本代码,并针对在执行过程中遇到的NoResultSetToFetchFrom错误进行了讨论。作者通过调整查询结果获取方式解决了该问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

新人学习python。学习慕课网的python操作mysql课程。https://www.imooc.com/video/9219

然后进行都最后发现,卡在了扣钱上面,会显示No result set to fetch from。

以下是源码:

# -$- coding:utf-8 -*-

"""
@author:Zhang
@file:transfer_money.py
@time:2018-02-19 1:48
"""
import sys
import mysql.connector

class TransferMoney(object):
    def __init__(self,conn):
        self.conn = conn

    def check_acct_available(self,accid):
        try:
            cursor = self.conn.cursor()
            sql = "SELECT * FROM account WHERE accid=%s" % accid
            cursor.execute(sql)
            print("check_acct_available:" + sql)
            rs = cursor.fetchall()
            if len(rs)!=1:
                raise Exception("账号%s不存在" % accid)
        finally:
            cursor.close()

    def has_enough_money(self,accid,money):
        try:
            cursor = self.conn.cursor()
            sql = "SELECT * FROM account WHERE accid=%s and money>%s" % (accid,money)
            cursor.execute(sql)
            print("has_enough_money:" + sql)
            rs = cursor.fetchall()
            if len(rs) != 1:
                raise Exception("账号%s没有足够钱" % accid)
        finally:
            cursor.close()

    def redue_money(self,accid,money):
        try:
            cursor = self.conn.cursor()
            sql = "UPDATE account SET money=money-%s WHERE accid=%s" % (money,accid)
            cursor.execute(sql)
            print("reduce_money:" + sql)
            rs = cursor.fetchall()
            if cursor.rowcount != 1:
                raise Exception("账号%s减款失败" % accid)
        finally:
            cursor.close()

    def add_money(self,accid,money):
        try:
            cursor = self.conn.cursor()
            sql = "UPDATE account SET money=money+%s WHERE accid=%s" % (money,accid)
            cursor.execute(sql)
            print("add_money:" + sql)
            rs = cursor.fetchall()
            if cursor.rowcount != 1:
                raise Exception("账号%s加款失败" % accid)
        finally:
            cursor.close()

    def transfer(self,souce_accid,target_accid,money):
        try:
            self.check_acct_available(source_accid)
            self.check_acct_available(target_accid)
            self.has_enough_money(source_accid,money)
            # 以上检验都成功的话
            self.redue_money(source_accid,money)
            self.add_money(target_accid,money)
            self.conn.commit()
        except Exception as e:
            self.conn.rollback()
            raise e

if __name__ == "__main__":
    source_accid = sys.argv[1]
    target_accid = sys.argv[2]
    money = sys.argv[3]

    conn = mysql.connector.connect(host="127.0.0.1",user="root",password="password",port=3306,db="test")
    tr_money = TransferMoney(conn)

    try:
        tr_money.transfer(source_accid,target_accid,money)
    except Exception as e:
        print("出现问题:"+str(e))
    finally:
        conn.close()

我发现问题在于,是python操作mysql抛出unread result from。

然后我就先把

rs = cursor.fetchall()

给注释掉..或者改成 cursor.fetchone() 就能顺利运行了。

还不知道本质原理,但是方法先放着。弄清楚了回来补上。


import sys import pymysql from PyQt5.QtWidgets import ( QApplication, QMainWindow, QWidget, QDialog, QTableWidgetItem, QMessageBox, QHeaderView, QPushButton, QLineEdit, QComboBox, QLabel, QVBoxLayout, QHBoxLayout, QFormLayout, QGroupBox, QTableWidget ) from PyQt5.QtCore import Qt from PyQt5.QtGui import QIcon, QIntValidator, QRegExpValidator from PyQt5.QtCore import QRegExp # 数据库配置,与原系统保持一致 DB_CONFIG = { 'host': '127.0.0.1', 'user': 'root', 'password': '123456', 'database': 'studentscore', 'charset': 'utf8mb4' } class LoginDialog(QDialog): """登录窗口""" def __init__(self): super().__init__() self.setWindowTitle("专业管理系统登录") self.setFixedSize(350, 200) # 设置登录窗口的背景颜色为淡蓝色 self.setStyleSheet("background-color: #e0f7fa;") # 创建布局 layout = QVBoxLayout() # 表单组 form_group = QGroupBox("数据库登录信息") form_layout = QFormLayout() self.txt_host = QLineEdit() self.txt_host.setText(DB_CONFIG['host']) self.txt_host.setPlaceholderText("数据库主机地址") self.txt_user = QLineEdit() self.txt_user.setText(DB_CONFIG['user']) self.txt_user.setPlaceholderText("数据库用户名") self.txt_pass = QLineEdit() self.txt_pass.setText(DB_CONFIG['password']) self.txt_pass.setPlaceholderText("数据库密码") self.txt_pass.setEchoMode(QLineEdit.Password) self.txt_db = QLineEdit() self.txt_db.setText(DB_CONFIG['database']) self.txt_db.setPlaceholderText("数据库名称") form_layout.addRow("主机:", self.txt_host) form_layout.addRow("用户名:", self.txt_user) form_layout.addRow("密码:", self.txt_pass) form_layout.addRow("数据库:", self.txt_db) form_group.setLayout(form_layout) # 按钮组 btn_layout = QHBoxLayout() self.btn_login = QPushButton("登录") self.btn_login.clicked.connect(self.attempt_login) self.btn_exit = QPushButton("退出") self.btn_exit.clicked.connect(self.reject) btn_layout.addWidget(self.btn_login) btn_layout.addWidget(self.btn_exit) # 添加到主布局 layout.addWidget(form_group) layout.addLayout(btn_layout) self.setLayout(layout) def attempt_login(self): """尝试登录""" config = { 'host': self.txt_host.text().strip(), 'user': self.txt_user.text().strip(), 'password': self.txt_pass.text().strip(), 'database': self.txt_db.text().strip(), 'charset': 'utf8mb4' } if not all(config.values()): QMessageBox.warning(self, "输入不完整", "请填写所有数据库连接信息") return try: # 测试数据库连接 conn = pymysql.connect(**config) # 检查bmajor表是否存在 with conn.cursor() as cursor: cursor.execute("SHOW TABLES LIKE 'bmajor'") if not cursor.fetchone(): QMessageBox.critical(self, "表不存在", "数据库中未找到bmajor表") return conn.close() # 更新全局配置 global DB_CONFIG DB_CONFIG = config self.accept() # 关闭对话框并返回QDialog.Accepted except pymysql.Error as e: QMessageBox.critical(self, "连接失败", f"数据库连接失败:\n{str(e)}") class MajorManager(QMainWindow): """专业管理主窗口""" def __init__(self): super().__init__() self.setWindowTitle("专业信息管理系统") self.setGeometry(100, 100, 1000, 600) # 创建中央部件 central_widget = QWidget() self.setCentralWidget(central_widget) # 主布局 main_layout = QVBoxLayout(central_widget) # 搜索功能区 search_group = QGroupBox("专业搜索") search_layout = QHBoxLayout() self.lbl_search = QLabel("专业名称:") self.txt_search = QLineEdit() self.txt_search.setPlaceholderText("输入专业名称关键字...") self.btn_search = QPushButton("搜索") self.btn_search.clicked.connect(self.search_major) self.btn_refresh = QPushButton("刷新数据") self.btn_refresh.clicked.connect(self.load_data) search_layout.addWidget(self.lbl_search) search_layout.addWidget(self.txt_search) search_layout.addWidget(self.btn_search) search_layout.addWidget(self.btn_refresh) search_group.setLayout(search_layout) # 数据表格 self.table = self.create_table() # 操作按钮区 btn_group = QGroupBox("专业操作") btn_layout = QHBoxLayout() self.btn_add = QPushButton("添加专业") self.btn_add.clicked.connect(self.add_major) self.btn_edit = QPushButton("编辑专业") self.btn_edit.clicked.connect(self.edit_major) self.btn_delete = QPushButton("删除专业") self.btn_delete.clicked.connect(self.delete_major) btn_layout.addWidget(self.btn_add) btn_layout.addWidget(self.btn_edit) btn_layout.addWidget(self.btn_delete) btn_group.setLayout(btn_layout) # 添加到主布局 main_layout.addWidget(search_group) main_layout.addWidget(self.table, 1) # 表格占据更多空间 main_layout.addWidget(btn_group) # 状态栏 self.statusBar().showMessage("就绪") # 加载数据 self.load_data() def create_table(self): """创建专业表格""" table = QTableWidget() table.setColumnCount(4) table.setHorizontalHeaderLabels(["专业ID", "专业名称", "院系ID", "院系名称"]) table.horizontalHeader().setSectionResizeMode(QHeaderView.Stretch) table.verticalHeader().setVisible(False) table.setSelectionBehavior(QTableWidget.SelectRows) table.setEditTriggers(QTableWidget.NoEditTriggers) table.setSortingEnabled(True) return table def get_connection(self): """获取数据库连接""" return pymysql.connect(**DB_CONFIG) def load_data(self): """从数据库加载专业数据""" try: conn = self.get_connection() with conn.cursor() as cursor: # 查询bmajor表的所有数据 cursor.execute("SELECT major_id, major_name, depart_id, depart_name FROM bmajor") result = cursor.fetchall() self.table.setRowCount(len(result)) for row_idx, row in enumerate(result): for col_idx, col in enumerate(row): item = QTableWidgetItem(str(col) if col is not None else "") self.table.setItem(row_idx, col_idx, item) conn.close() self.statusBar().showMessage(f"成功加载 {len(result)} 条专业记录") except pymysql.Error as e: QMessageBox.critical(self, "数据库错误", f"加载数据失败:\n{str(e)}") self.statusBar().showMessage("数据加载失败") def add_major(self): """添加新专业""" dialog = MajorDialog(self) if dialog.exec_() == QDialog.Accepted: major_data = dialog.get_data() try: conn = self.get_connection() with conn.cursor() as cursor: sql = """INSERT INTO bmajor (major_id, major_name, depart_id, depart_name) VALUES (%s, %s, %s, %s)""" cursor.execute(sql, major_data) conn.commit() self.load_data() self.statusBar().showMessage(f"成功添加专业: {major_data[1]}") except pymysql.IntegrityError as e: if "Duplicate entry" in str(e): QMessageBox.critical(self, "添加失败", "专业ID或专业名称已存在") else: QMessageBox.critical(self, "添加失败", f"添加专业失败:\n{str(e)}") except pymysql.Error as e: QMessageBox.critical(self, "添加失败", f"添加专业失败:\n{str(e)}") def edit_major(self): """编辑选中专业""" selected = self.table.currentRow() if selected < 0: QMessageBox.warning(self, "未选择", "请先选择要编辑的专业") return major_id = self.table.item(selected, 0).text() dialog = MajorDialog(self, major_id) if dialog.exec_() == QDialog.Accepted: major_data = dialog.get_data() try: conn = self.get_connection() with conn.cursor() as cursor: sql = """UPDATE bmajor SET major_name = %s, depart_id = %s, depart_name = %s WHERE major_id = %s""" # 注意顺序: name, depart_id, depart_name, id cursor.execute(sql, ( major_data[1], major_data[2], major_data[3], major_data[0] )) conn.commit() self.load_data() self.statusBar().showMessage(f"成功更新专业: {major_data[1]}") except pymysql.Error as e: QMessageBox.critical(self, "更新失败", f"更新专业失败:\n{str(e)}") def delete_major(self): """删除选中专业""" selected = self.table.currentRow() if selected < 0: QMessageBox.warning(self, "未选择", "请先选择要删除的专业") return major_id = self.table.item(selected, 0).text() major_name = self.table.item(selected, 1).text() reply = QMessageBox.question(self, "确认删除", f"确定要删除专业 '{major_name}' (ID: {major_id}) 吗?", QMessageBox.Yes | QMessageBox.No) if reply == QMessageBox.Yes: try: conn = self.get_connection() with conn.cursor() as cursor: cursor.execute("DELETE FROM bmajor WHERE major_id = %s", (major_id,)) conn.commit() self.load_data() self.statusBar().showMessage(f"已删除专业: {major_name}") except pymysql.Error as e: # 检查是否有外键约束 if "foreign key constraint" in str(e).lower(): QMessageBox.critical(self, "删除失败", "该专业可能被其他表引用,无法删除") else: QMessageBox.critical(self, "删除失败", f"删除专业失败:\n{str(e)}") def search_major(self): """搜索专业""" keyword = self.txt_search.text().strip() if not keyword: self.load_data() return try: conn = self.get_connection() with conn.cursor() as cursor: cursor.execute("SELECT major_id, major_name, depart_id, depart_name " "FROM bmajor WHERE major_name LIKE %s", (f"%{keyword}%",)) result = cursor.fetchall() self.table.setRowCount(len(result)) for row_idx, row in enumerate(result): for col_idx, col in enumerate(row): item = QTableWidgetItem(str(col) if col is not None else "") self.table.setItem(row_idx, col_idx, item) conn.close() self.statusBar().showMessage(f"找到 {len(result)} 条匹配专业") except pymysql.Error as e: QMessageBox.critical(self, "搜索失败", f"搜索专业失败:\n{str(e)}") class MajorDialog(QDialog): """专业编辑对话框""" def __init__(self, parent=None, major_id=None): super().__init__(parent) self.setWindowTitle("添加专业" if not major_id else "编辑专业") self.setFixedSize(400, 350) # 主布局 layout = QVBoxLayout() # 表单布局 form_layout = QFormLayout() self.txt_id = QLineEdit() self.txt_id.setPlaceholderText("2位专业代码") # 设置专业ID验证器,必须是2位字母或数字 id_validator = QRegExpValidator(QRegExp(r'^[a-zA-Z0-9]{2}$')) self.txt_id.setValidator(id_validator) self.txt_name = QLineEdit() self.txt_name.setPlaceholderText("输入专业名称") self.txt_depart_id = QLineEdit() self.txt_depart_id.setPlaceholderText("2位院系代码") # 设置院系ID验证器,必须是2位字母或数字 depart_id_validator = QRegExpValidator(QRegExp(r'^[a-zA-Z0-9]{2}$')) self.txt_depart_id.setValidator(depart_id_validator) self.txt_depart_name = QLineEdit() self.txt_depart_name.setPlaceholderText("输入院系名称") form_layout.addRow("专业ID:", self.txt_id) form_layout.addRow("专业名称:", self.txt_name) form_layout.addRow("院系ID:", self.txt_depart_id) form_layout.addRow("院系名称:", self.txt_depart_name) # 按钮布局 btn_layout = QHBoxLayout() self.btn_save = QPushButton("保存") self.btn_save.clicked.connect(self.validate_and_accept) self.btn_cancel = QPushButton("取消") self.btn_cancel.clicked.connect(self.reject) btn_layout.addStretch() btn_layout.addWidget(self.btn_save) btn_layout.addWidget(self.btn_cancel) # 添加到主布局 layout.addLayout(form_layout) layout.addLayout(btn_layout) self.setLayout(layout) # 如果是编辑模式,加载现有数据 self.major_id = major_id if major_id: self.load_major_data() self.txt_id.setEnabled(False) # 禁止编辑专业ID def load_major_data(self): """加载专业数据到表单""" try: conn = pymysql.connect(**DB_CONFIG) with conn.cursor() as cursor: cursor.execute("SELECT * FROM bmajor WHERE major_id = %s", (self.major_id,)) result = cursor.fetchone() if result: self.txt_id.setText(result[0]) self.txt_name.setText(result[1]) self.txt_depart_id.setText(result[2] if result[2] is not None else "") self.txt_depart_name.setText(result[3] if result[3] is not None else "") conn.close() except pymysql.Error as e: QMessageBox.critical(self, "加载失败", f"加载专业数据失败:\n{str(e)}") def get_data(self): """从表单获取数据""" # 处理可能为空的值 def get_value_or_none(text): return text.strip() if text.strip() else None return ( self.txt_id.text().strip(), self.txt_name.text().strip(), get_value_or_none(self.txt_depart_id.text()), get_value_or_none(self.txt_depart_name.text()) ) def validate_and_accept(self): """验证表单数据并接受""" # 验证专业ID格式 major_id = self.txt_id.text().strip() if len(major_id) != 2: QMessageBox.warning(self, "格式错误", "专业ID必须是2位字符") return # 验证必填字段 if not self.txt_name.text().strip(): QMessageBox.warning(self, "输入不完整", "专业名称不能为空") return # 验证院系ID depart_id = self.txt_depart_id.text().strip() if depart_id and len(depart_id) != 2: QMessageBox.warning(self, "格式错误", "院系ID必须是2位字符") return super().accept() if __name__ == "__main__": app = QApplication(sys.argv) # 显示登录窗口 login = LoginDialog() if login.exec_() != QDialog.Accepted: sys.exit() # 显示主窗口 window = MajorManager() window.show() sys.exit(app.exec_())
最新发布
06-24
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值