You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python Tkinter连接SQLite3删除数据异常原因排查

问题:删除学生及关联咨询记录后数据残留的异常原因分析

背景

通过以下create_table函数创建了students和counseling_records两张表:

def create_table(conn):
    cursor = conn.cursor()
    cursor.execute('''CREATE TABLE IF NOT EXISTS students
                   (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT UNIQUE)''')
    cursor.execute('''CREATE TABLE IF NOT EXISTS counseling_records
                      (id INTEGER PRIMARY KEY AUTOINCREMENT, student_id INTEGER, title TEXT, counseling_text TEXT, record_datetime TEXT,
                       FOREIGN KEY(student_id) REFERENCES students(id))''')
    conn.commit()

调用中间函数后,使用以下delete_student函数删除学生及关联的咨询记录时,首次运行提示删除成功,但再次操作时发现数据库中仍有残留数据,无法正常完成删除。

def delete_student():
    selected_index = student_listbox.curselection()
    if selected_index:
        student_name = student_listbox.get(selected_index)
        confirmed = messagebox.askyesno("确认", f"{student_name}을(를) 삭제하시겠습니까?")
        if confirmed:
            cursor = conn.cursor()
            # 按学生姓名查询学生id
            cursor.execute("SELECT id FROM students WHERE name=?", (student_name,))
            student_id = cursor.fetchone()
            if student_id:
                # 删除学生关联的咨询记录
                cursor.execute("DELETE FROM counseling_records WHERE student_id=?", (student_id[0],))
                # 删除学生
                cursor.execute("DELETE FROM students WHERE id=?", (student_id[0],))
                conn.commit()
                student_listbox.delete(selected_index)
                messagebox.showinfo("通知", f"{student_name}이(가) 성공적으로 삭제되었습니다.")
            else:
                messagebox.showwarning("警告", f"{student_name}을(를) 찾을 수 없습니다.")

异常原因分析

最可能的几个原因:

1. SQLite外键约束未启用

SQLite默认关闭外键约束检查,即便表结构中定义了外键关联,默认情况下这个约束不会生效。你的代码逻辑是先删关联记录再删学生,本身不依赖外键约束,但如果后续有其他操作插入关联记录,或者删除过程中出现约束相关的隐性错误,可能导致数据残留。

解决方法:创建数据库连接后立即开启外键约束:

conn.execute("PRAGMA foreign_keys = ON")

2. 数据库连接对象不一致

如果create_table使用的conn和delete_student中的conn不是同一个实例,会导致删除操作的提交只在当前连接会话中生效,其他连接读取数据库时仍会看到旧数据。比如你在某个函数中创建了局部连接并关闭,后续delete_student又重新创建另一个连接,或者全局conn变量被意外重新赋值,都可能出现这种情况。

3. 事务未正确提交或存在未处理异常

虽然代码中调用了conn.commit(),但如果commit()执行前发生未捕获的异常(比如UI操作报错),会导致事务回滚,删除操作并未真正写入数据库。另外,程序中若存在其他未提交的事务,也可能干扰当前删除操作的生效。

4. 多线程共享同一个数据库连接

SQLite的连接对象不是线程安全的,如果程序中存在多线程同时操作同一个conn,可能导致事务执行异常,出现数据删除不彻底的情况。

内容的提问来源于stack exchange,提问作者kiz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 15:20:59