user432584920684
user432584920684

Reputation: 389

SQLite / Python database retrieval and comparison

At the moment, I have a database which contains username, password, etc. I am wishing to look into the database to check if duplicates are in there.

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"

Here is my code at the moment. newID is a new name and I wish to check if there are any existing entries in the database with the same name.

My question is - is the way I am doing it in my code a good idea? I'm mainly concerned with my approach. Should I be using something other than fetchall() ?

Thank you for your time! :) P.S. This is for a website application.

Upvotes: 4

Views: 2906

Answers (2)

Li-aung Yip
Li-aung Yip

Reputation: 12486

Here's a way to do exactly what you asked for - find out if a given username already exists:

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':"[email protected]"},
    {'username':"Billy",    'email':"[email protected]"},
    {'username':"Charles",  'email':"[email protected]"},
    {'username':"Dick",     'email':"[email protected]"},
    {'username':"Emily",    'email':"[email protected]"},
    {'username':"Faramir",  'email':"[email protected]"},
)

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

Since all you want is a COUNT this is adequate.


Really, though, you shouldn't be enforcing the uniqueness of the usernames yourself. Let the database do that for you by specifying the field to be either UNIQUE or PRIMARY KEY.

If you try to insert "Alice", "[email protected]" after creating the database like above, this will get you an sqlite3.IntegrityError:

>>> conn.execute("""INSERT INTO users (username, email)
...                     VALUES ("Alice", "[email protected]");""")
Traceback (most recent call last):
  File "<stdin>", line 2, in <module>
sqlite3.IntegrityError: column username is not unique

To detect this, try to run the INSERT and detect whether it fails.

try:
    conn.execute("""INSERT INTO users (username, email)
                    VALUES ("Alice", "[email protected]");""")
except sqlite3.IntegrityError:
    print ("Username 'Alice' was already taken.")

Incidentally, be very careful with using the upper/lowercase functions. Does "Главное в новостях".lower() mean what you think it means?


Since you mention this is for a webapp, I'll just remind you to store your passwords as salted hashes of the password, using unique salts for each user (never as plain text!), and to guard against SQL injection by using the (?,?,?,?,...) placeholders for SQL queries, not the (%s,%s) % (var1, var2) string interpolation method.

To quote the sqlite3 documentation:

Usually your SQL operations will need to use values from Python variables. You shouldn’t assemble your query using Python’s string operations because doing so is insecure; it makes your program vulnerable to an SQL injection attack.

Instead, use the DB-API’s parameter substitution. Put ? as a placeholder wherever you want to use a value, and then provide a tuple of values as the second argument to the cursor’s execute() method. (Other database modules may use a different placeholder, such as %s or :1.) For example:

If you don't do this, then someone could request the username Robert Menzies; DROP TABLE users; with hilarious results.

Upvotes: 5

daniel
daniel

Reputation: 403

Why not set the field in SQLite to unique which will prevent duplicate entries in the first place.

Upvotes: 0

Related Questions