如何在Python3.7+SQLite3中阻止空f_name记录写入数据库?
解决方法:在插入数据库前验证输入并修正调试逻辑
看起来你遇到的核心问题是没有正确获取并验证输入框的实际值,而且错误地在执行插入操作后才做校验——这时候已经晚了,哪怕不commit,插入指令已经发送给数据库了。下面给你一步步的解决方案:
1. 先获取并清洗输入值,再做校验
首先,你需要先把输入框的内容取出来(调用.get()),并且去掉前后空白字符(避免用户只输入空格的情况),然后再检查是否为空。不要直接操作控件对象(比如你打印f_name得到的.!entry2是Tkinter Entry控件的内部名称,不是用户输入的内容)。
2. 修改后的完整submit()函数
def submit(): # 先获取并清洗所有输入值 first_name = f_name.get().strip() last_name = l_name.get().strip() address_val = address.get().strip() city_val = city.get().strip() state_val = state.get().strip() zipcode_val = zipcode.get().strip() # 核心校验:检查first_name是否为空 if not first_name: print("No valid Data in First name field") # 这里也可以弹出Tkinter提示框优化体验,比如: # from tkinter import messagebox # messagebox.showwarning("输入错误", "名字不能为空") return # 直接返回,不执行后续数据库操作 # 初始化提醒相关变量 six_month_reminder = "f" annual_reminder = "f" six_month_reminder_sent = "f" annual_reminder_sent = "f" # 连接数据库并插入数据 conn = sqlite3.connect('address_book.db') c = conn.cursor() # 只有校验通过才执行插入 c.execute("INSERT INTO addresses VALUES (:f_name, :l_name, :address, :city, :state, :zipcode, :six_month_reminder, :annual_reminder, :six_month_reminder_sent, :annual_reminder_sent)", { 'f_name': first_name, 'l_name': last_name, 'address': address_val, 'city': city_val, 'state': state_val, 'zipcode': zipcode_val, 'six_month_reminder': six_month_reminder, 'annual_reminder': annual_reminder, 'six_month_reminder_sent': six_month_reminder_sent, 'annual_reminder_sent': annual_reminder_sent }) conn.commit() conn.close() # 可选:清空输入框,提升用户体验 f_name.delete(0, END) l_name.delete(0, END) address.delete(0, END) city.delete(0, END) state.delete(0, END) zipcode.delete(0, END)
3. 额外的双重保障:数据库层面加约束
为了避免程序逻辑漏判,你可以给addresses表的f_name字段添加NOT NULL约束,这样即使程序出现问题,数据库也会拒绝插入空值:
-- 如果表还未创建,创建时直接加上约束 CREATE TABLE addresses ( f_name TEXT NOT NULL, l_name TEXT, address TEXT, city TEXT, state TEXT, zipcode TEXT, six_month_reminder TEXT, annual_reminder TEXT, six_month_reminder_sent TEXT, annual_reminder_sent TEXT ); -- 如果表已存在,SQLite需要先备份数据再重建表(SQLite对ALTER TABLE修改约束支持有限)
为什么你之前的方法无效?
- 你之前在
conn.commit()前加判断,但此时c.execute()已经执行了,虽然不commit不会永久写入,但最好是根本不执行插入操作,更高效也更安全。 - 你打印
f_name得到.!entry2,是因为你打印的是Entry控件对象本身,而不是用户输入的内容——正确的做法是打印f_name.get()来查看实际输入值。
内容的提问来源于stack exchange,提问作者Markal




