有客自远方来52 2024-02-13 15:13 采纳率: 15.3%
浏览 3
已结题

为什么会重复插入数据, 是python代码写错了吗(开发工具-pycharm)

下面是我的代码和重复插入数据的图片


def add(book: Book) -> int:
    con = None
    try:
        con = dbUtil.getCon()
        cursor = con.cursor()
        # 插入数据
        cursor.execute(
            "DECLARE @B INT SET @B=(SELECT TOP 1 ID FROM t_book order by ID DESC)DBCC CHECKIDENT('t_book',"
            "RESEED,@B)")
        sql = f"insert into t_book (bookName,author,age,sex,price,TID, bookDesc) values ('{book.bookName}','{book.author}','{book.age}','{book.sex}',{book.price},{book.TID},'{book.bookDesc}');"
        cursor.execute(sql)
        con.commit()
        return cursor.rowcount
    except Exception as e:
        print(f"插入数据时发生错误: {e}")
        if con is not None:
            con.rollback()
        return 0
    finally:
        dbUtil.closeCon(con)


def add(self):
    """
    添加图书信息
    :return:
    """
    bookName = self.bookNameInput.text()
    if bookName.strip() == "":
        QMessageBox.warning(None, '系统提示', '图书名称不能为空!')
        return
    author = self.authorInput.text()
    if author.strip() == "":
        QMessageBox.warning(None, '系统提示', '图书作者不能为空!')
        return
    age = self.ageInput.text()
    if age.strip() == "":
        QMessageBox.warning(None, '系统提示', '年龄不能为空!')
        return
    sex = ''
    if self.manRadio.isChecked():
        sex = '男'
    else:
        sex = '女'
    price = self.priceInput.text()
    if price.strip() == "":
        QMessageBox.warning(None, '系统提示', '图书价格不能为空!')
        return
    TID = self.bookTypeComboBox.currentData()
    if bookName == -1:
        QMessageBox.warning(None, '系统提示', '请选择图书类别!')
        return

    bookDesc = self.bookDescInput.toPlainText()
    book = Book.my_construtor(bookName, author, age, sex, price, TID, bookDesc)
    if bookDao.add(book) is not None and bookDao.add(book) > 0:
        QMessageBox.information(None, '系统提示', '添加成功!')
        self.reset()
    else:
        QMessageBox.warning(None, '系统提示', '添加失败!')

def reset(self):
    self.bookNameInput.setText("")
    self.authorInput.setText("")
    self.ageInput.setText("")
    self.manRadio.setChecked(True)
    self.priceInput.setText("")
    self.bookTypeComboBox.setCurrentIndex(0)
    self.bookDescInput.setPlainText("")

img

  • 写回答

3条回答 默认 最新

  • 专家-赤兔[在线] 优质创作者: 编程框架技术领域 2024-02-13 15:15
    关注

    引自免费微信小程序:皆我百晓生

    根据您提供的代码片段,我注意到您在处理数据库插入操作时存在可能导致重复插入的问题。但在这个场景下,并未直接发现导致数据重复插入的明显错误。不过,结合您的问题,我们可以分析以下几个可能的原因:

    1. 触发机制问题: 您在add函数中调用了bookDao.add(book)方法两次。虽然您没有展示bookDao.add(book)的具体实现,但如果这个方法内部执行了实际的数据插入操作,那么连续调用两次就会造成重复插入。

    2. 用户界面交互逻辑: 在UI交互部分,reset函数会在添加成功后清空表单内容,但这里并没有限制用户在短时间内快速多次点击“添加”按钮,若不采取任何防止重复提交的措施(如禁用按钮或增加二次确认),可能会因为用户的误操作导致重复插入。

    3. 事务控制与并发问题: 虽然您在数据库操作中有try-except-finally结构,并且有commit和rollback的处理,但在多线程或多用户环境下,如果没有正确的事务隔离级别设置或其他并发控制手段,理论上还是有可能出现重复插入的情况。

    4. 主键生成策略: 您尝试通过查询并重新设置标识列种子来维持自增ID,但是这里的SQL语句逻辑看起来有些复杂,可能无法正确生成唯一的ID。如果ID不是唯一,或者在并发情况下该逻辑失效,则可能导致重复插入。建议使用数据库自身的序列(sequence)或者其他更为安全的方式来保证主键的唯一性。

    为了解决这个问题,请检查以下几点以避免重复插入:

    • 确保bookDao.add(book)只执行一次插入操作。
    • 对于用户界面交互,可以考虑在提交操作期间禁用“添加”按钮,直到操作完成。
    • 验证数据库中的主键约束是否有效,确保每条新记录插入时其主键值都是唯一的。
    • 如果需要手动管理主键,确保在高并发场景下的主键生成策略是线程安全的。

    由于没有提供完整的上下文以及数据库类型、表结构等信息,以上仅为可能性分析。针对具体的代码优化,您可以参考以下修改后的示例,假设bookDao.add(book)仅执行一次插入操作:

    def add(self):
        """
        添加图书信息
        :return:
        """
        # ... (前面的输入验证代码不变)
    
        bookDesc = self.bookDescInput.toPlainText()
        book = Book.my_construtor(bookName, author, age, sex, price, TID, bookDesc)
        
        # 只执行一次插入操作
        result = bookDao.add(book)
        
        if result is not None and result > 0:
            QMessageBox.information(None, '系统提示', '添加成功!')
            self.reset()
        else:
            QMessageBox.warning(None, '系统提示', '添加失败!')
    
        # 不再额外调用bookDao.add(book)
    

    对于主键ID生成的优化,建议查阅您所使用的数据库系统的官方文档,使用适合的方式来生成唯一且递增的ID,例如在MySQL中可以创建并使用AUTO_INCREMENT字段,在PostgreSQL中可以使用序列(SEQUENCE)。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

问题事件

  • 系统已结题 2月21日
  • 已采纳回答 2月13日
  • 创建了问题 2月13日