如何在使用python将数据插入sqlite3时在重复条目上引发错误消息?

Sun*_*jan 0 python sqlite tkinter

伙计我正在使用sqlite3和python tkinter作为前端.数据库很简单,有两个字段,用户名密码.我想进行注册注册页面.其中两个字段中给出的数据存储在sqlite3数据库中.数据正确插入.但是,当数据库中已存在提供的用户名时,我想显示一个消息框.我尝试了下面的代码.

我的代码:

def signup():
    userID = username.get()
    passwd = password.get()
    conn = sqlite3.connect('test.db')
    c = conn.cursor()
    result = c.execute("SELECT * FROM userstable")

    for i in result:
        if i[0] == userID:
            messagebox.showerror("DUPLICATE", "USER ALREADY EXISTS!")

    else:
        conn = sqlite3.connect('test.db')
        c = conn.cursor()
        c.execute("INSERT INTO userstable VALUES (?, ?)", (userID, passwd))
        conn.commit()
        c.close()
        conn.close()
        username.delete(0,END)
        password.delete(0,END)
        username.focus()
        messagebox.showinfo("SUCCESS", "USER CREATED SUCCESSFULLY")
Run Code Online (Sandbox Code Playgroud)

这可以工作,但仍然会在错误消息之后存储重复数据.如果用户名已经可用,我的要求是抛出错误并停止执行.如果用户名不可用,则应插入数据.

我哪里错了?有人可以通过指出来解释我,还是有其他方法可以达到这个目的?看来我需要修改一些功能.请指导我.

编辑1

如果我尝试使用三个条件,则休息不起作用.

我的代码

def data_entry():
    conn = sqlite3.connect('test.db')
    c = conn.cursor()
    c.execute('CREATE TABLE IF NOT EXISTS userstable(username TEXT, password TEXT)')
    username = uname.get()
    password = passwd.get()

    result = c.execute("SELECT * FROM userstable")

    if username != '' or password != '':

        for i in result:
            if i[0] == username:
                tkinter.messagebox.showerror("DUPLICATE", "USER ALREADY EXISTS!")
                break
        else: 
            c.execute('INSERT INTO userstable (username, password) VALUES(?, ?)',(username,password))
            conn.commit()
            c.close()
            conn.close()
            another_clear()
            tkinter.messagebox.showinfo("Success", "User Created Successfully,\nPlease restart application.")

    else:
        tkinter.messagebox.showerror("ERROR", "Fill both fields!")
Run Code Online (Sandbox Code Playgroud)

小智 5

解决此问题的更好方法是在表上创建唯一约束(索引,在sqlite中)以防止插入重复的用户名.这样,你可以尝试/除了insert语句,而不是循环遍历所有用户的列表,看它是否已经存在(那是不可扩展的).这也会阻止你"选择*",这通常是不好的做法(尽量明确).

https://sqlite.org/lang_createtable.html

因此,您可以将约束添加为唯一索引或主键.如果此表中只有2列,或者如果您有2个以上但没有其他ID,则您的用户名可以是您的主键.如果您要为用户引入系统ID,我会将其用作主键和用户名作为唯一索引.无论哪种方式,您都需要更改表以添加约束.

CREATE UNIQUE INDEX username_uidx ON userstable (username);
Run Code Online (Sandbox Code Playgroud)

同样,因为您没有明确地让我们知道列名称,所以您必须填写它.

之后:

try:
    conn = sqlite3.connect('test.db')
    c = conn.cursor()
    c.execute("INSERT INTO userstable VALUES (?, ?)", (userID, passwd))
    conn.commit()
except: # I'm not sure the exact error that's raised by SQLite
    messagebox.showerror("DUPLICATE", "USER ALREADY EXISTS!")
finally:
    c.close()
    conn.close()
Run Code Online (Sandbox Code Playgroud)

我通常将我的光标和连接包装在finally中,以便即使存在异常也会关闭它们.这不是你所需要的100%,但它应该让你在一步中通过更好的数据库设计来强制执行用户的唯一性.