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

时间:2017-05-25 16:40:15

标签: python tkinter sqlite

伙计们我使用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")

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

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

编辑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!")

2 个答案:

答案 0 :(得分:5)

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

https://sqlite.org/lang_createtable.html

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

CREATE UNIQUE INDEX username_uidx ON userstable (username);

同样,因为您没有明确地让我们知道列名称,所以您必须将其填入。

之后:

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()

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

答案 1 :(得分:1)

我建议不要使用带有else语句的循环,这可能令人困惑 有关详情,请参阅此帖why-does-python-use-else-after-for-and-while-loops

如果你想使用 - 否则你可以添加一个中断,所以不会执行:

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

或者您可以使用true / false标志:

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