2012-03-19 2 views
4

На данный момент у меня есть база данных, которая содержит имя пользователя, пароль и т. Д. Я хочу посмотреть в базу данных, чтобы проверить, есть ли там дубликаты.Поиск и сравнение базы данных SQLite/Python

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" 

Вот мой код на данный момент. newID - это новое имя, и я хочу проверить, есть ли какие-либо существующие записи в базе данных с тем же именем.

Мой вопрос в том, насколько я делаю это в своем коде - хорошая идея? Я в основном обеспокоен моим подходом. Должен ли я использовать что-то другое, чем fetchall()?

Благодарим вас за внимание! :) P.S. Это приложение для веб-сайта.

+0

Чтобы сохранить память, рассмотрите возможность замены 'fetchall()' на 'fetchone()'. – Dikei

ответ

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':"[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 

Поскольку все, что вы хотите это COUNT это адекватно.


Действительно, вы не должны применять уникальность самих имен пользователей. Пусть база данных сделает это для вас, указав поле как UNIQUE или PRIMARY KEY.

Если вы пытаетесь вставить "Alice", "[email protected]" после создания базы данных, как выше, это поможет вам 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 

Чтобы обнаружить это, попробуйте запустить INSERT и обнаружить не удается ли.

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

Кстати, будьте очень осторожны с использованием функций верхнего и нижнего регистра. Имеет ли значение "Главное в новостях".lower() то, что вы думаете, что это значит?


Поскольку вы упоминаете это на веб-приложение, я просто напоминаю вам хранить ваши пароли salted hashes of the password, using unique salts for each user (не как обычный текст!), А также для защиты от инъекции SQL, используя (?,?,?,?,...) заполнители для запросов SQL , а не метод интерполяции строк (%s,%s) % (var1, var2).

процитировать 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:

Если вы не сделаете этого, то кто-то может запросить имя пользователя Robert Menzies; DROP TABLE users; с hilarious results.

+0

Благодарим вас за прекрасное объяснение. Очень ценится. Просто из любопытства, что делает «Роберт Мензис; Пользователи DROP TABLE: 'действительно делаете и почему? Thans! – user432584920684

+0

На самом деле имя должно быть «Robert Menzies»; DROP TABLE users; '. Затем, если ваш запрос похож на «INSERT INTO users VALUES (% s)«% username », то после подстановки переменных вы будете иметь« INSERT INTO users VALUES (Robert Menzies), DROP TABLE users; '- Robert Menzies' в таблицу 'users', затем ** удалите всю таблицу' users'. ** –

+1

Это называется атакой SQL-инъекции, и это возможно, потому что символ ';' заканчивает команду SQL и начинает новую . ** Один из вещей, которые вам нужно сделать, - это escape ';' символов в пользовательском вводе, чтобы этого не произошло. Использование рекомендуемой практики - '(?,?,? ...)' placeholders - в Документация 'sqlite3' будет защищать эту атаку и многое другое. –

0

Почему бы не задать поле в SQLite уникальным, что предотвратит дублирование записей в первую очередь.

+0

Что произойдет, если обнаружена дублирующаяся запись? – user432584920684

+0

@ Vincent, если вы установили имя пользователя colummn уникальным и вставить в таблицу Users с уже существующим именем пользователя, это приведет к сбою. например во-первых, никогда не будет дублирования. – daniel

+0

Так будет ли моя программа по существу «сбой»? Извините, я новичок и только начинаю с кодирования. Ваша помощь очень ценится. – user432584920684

Смежные вопросы