SQLite/Python数据库检索和比较

use*_*684 4 python sqlite

目前,我有一个包含用户名,密码等的数据库.我希望查看数据库以检查是否有重复项.

con = lite.connect('userInfo.db')
with con:
    cur = con.cursor()
    cur.execute("SELECT * FROM Users WHERE LOWER(Username) = LOWER(?)", (newID,))
    rows = cur.fetchall()
    if len(rows)!=0:
        return "Duplicate detected"
Run Code Online (Sandbox Code Playgroud)

这是我目前的代码.newID是一个新名称,我希望检查数据库中是否存在任何具有相同名称的现有条目.

我的问题是 - 我在代码中这样做的方式是个好主意吗?我主要关心的是我的做法.我应该使用其他东西fetchall()吗?

感谢您的时间!:) PS这是一个网站应用程序.

Li-*_*Yip 5

这是一种完全符合您要求的方法 - 查明给定是否username已存在:

import sqlite3
conn = sqlite3.connect(":memory:")
conn.execute ("""
              CREATE TABLE users (
                  uid INTEGER PRIMARY KEY AUTOINCREMENT,
                  username TEXT UNIQUE,
                  email TEXT UNIQUE );
             """)

test_users = (
    {'username':"Alice",    'email':"Alice@mail.com"},
    {'username':"Billy",    'email':"Billy@mail.com"},
    {'username':"Charles",  'email':"Charles@mail.com"},
    {'username':"Dick",     'email':"Dick@mail.com"},
    {'username':"Emily",    'email':"Emily@mail.com"},
    {'username':"Faramir",  'email':"Faramir@mail.com"},
)

for user in test_users:
    conn.execute("INSERT INTO users (username, email) VALUES (?,?)",
                 (user['username'],user['email'])
                )

result = conn.execute("SELECT COUNT(*) FROM users WHERE username='Alice'")
number_of_Alices = result.next()[0] # number_of_Alices will be 1
Run Code Online (Sandbox Code Playgroud)

既然你想要的只是一个COUNT就足够了.


但实际上,您不应该自己强制执行用户名的唯一性.让数据库通过将字段指定为UNIQUE或来为您执行此操作PRIMARY KEY.

如果您"Alice", "alice@wonderland.com"在创建上述数据库后尝试插入,则会出现sqlite3.IntegrityError:

>>> conn.execute("""INSERT INTO users (username, email)
...                     VALUES ("Alice", "alice@wonderland.com");""")
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
sqlite3.IntegrityError: column username is not unique
Run Code Online (Sandbox Code Playgroud)

要检测到这一点,请尝试运行INSERT并检测它是否失败.

try:
    conn.execute("""INSERT INTO users (username, email)
                    VALUES ("Alice", "alice@wonderland.com");""")
except sqlite3.IntegrityError:
    print ("Username 'Alice' was already taken.")
Run Code Online (Sandbox Code Playgroud)

顺便说一句,使用大/小写函数要非常小心.你的"??????? ? ????????".lower()意思是什么意思?


既然你提到这是一个webapp,我只会提醒你将密码存储为密码的盐渍,使用每个用户的唯一盐(从不作为纯文本!),并使用(?,?,?,?,...)占位符防止SQL注入对于SQL查询,而不是(%s,%s) % (var1, var2)字符串插值方法.

引用sqlite3文档:

通常,您的SQL操作需要使用Python变量中的值.你不应该使用Python的字符串操作来组装你的查询,因为这样做是不安全的; 它使您的程序容易受到SQL注入攻击.

而是使用DB-API的参数替换.放?作为占位符,无论您想要使用哪个值,然后提供一个值元组作为游标的execute()方法的第二个参数.(其他数据库模块可能使用不同的占位符,例如%s或:1.)例如:

如果你不这样做,那么有人可以请求Robert Menzies; DROP TABLE users;具有搞笑结果的用户名.