#python #sqlite #if-statement
#python #sqlite #if-statement
Вопрос:
Я хочу написать фрагмент кода, в котором я хочу импортировать файлы из базы данных SQLite, а затем проверить, есть ли уже запись с такими же атрибутами, и в этом случае я не хочу запускать часть моего оператора if.
for entry in entries:
if beer.name not in entries[3]:
print(f'New beer found: {beer.name}')
print(f'Beer price: {beer.price}')
beer.rating, beer.unt_id, beer.style = untappd_scraper(beer)
if beer.unt_id is not entry[4]:
if site == "Hopt":
c.execute("INSERT INTO beers VALUES (:a, :b, :c, :g, :e, :f)", {'a': beer.name, 'b': beer.style, 'c': beer.rating,'g': beer.unt_id, 'e': beer.price, 'f': ''})
# conn.commit()
elif site == "Beerdome":
c.execute(
"INSERT INTO beers VALUES (:a, :b, :c, :g, :e, :f)", {'a': beer.name, 'b': beer.style, 'c': beer.rating, 'g': beer.unt_id, 'e': '', 'f': beer.price})
# conn.commit()
conn.commit()
Похоже, это не работает, поскольку пиво просто продолжает добавляться, даже если оно уже несколько раз в списке.
Итак, как я могу изменить этот код, чтобы он работал?
Комментарии:
1. Привет, спасибо за ответ. Он по-прежнему добавляет одно и то же пиво снова и снова, через некоторое время он решает перейти к новому пиву. Не понимаю, почему он распознает его через некоторое время.
Ответ №1:
Код в вопросах выглядит так, как будто был запрошен запрос к таблице базы данных, и теперь каждая строка проверяется, соответствует ли она деталям пива. Помимо опечаток, это вряд ли сработает, потому что будет вставлена новая строка beer, если какая-либо из строк не соответствует beer.
Предполагая, что таблица выглядит примерно так:
CREATE TABLE beers (
id INTEGER PRIMARY KEY,
name TEXT,
unt_id INTEGER)
мы можем получить подробную информацию о пиве, затем запросить, есть ли соответствующая строка, и вставить, если строка не найдена, например:
# Let's assume we have got a beer name AND unt_id.
name, unt_id = some_function_that_gets_beer_details()
cur.execute("""SELECT COUNT(1) FROM beers WHERE name = ? AND unt_id = ?""", (name, unt_id))
count, = cur.fetchone()
if count == 0:
# Beer not found, do insert
cur.execute("""INSERT INTO beers (name, unt_id) VALUES (?, ?)""", (name, unt_id))
conn.commit()
Это работает довольно хорошо, но если программу запускает более одного пользователя, возможно, что дубликат beer может быть добавлен путем вставки между запросом и вставкой (это известно как условие гонки). Мы можем предотвратить это, добавив в таблицу ограничение, , требующее, чтобы комбинация name
и unt_id
была уникальной. DDL для таблицы будет выглядеть следующим образом:
CREATE TABLE beers (
id INTEGER PRIMARY KEY,
name TEXT,
unt_id INTEGER,
CONSTRAINT uniq_name_unt UNIQUE (name, unt_id))
Или существующая таблица может быть обновлена с помощью этого SQL:
CREATE UNIQUE INDEX uniq_name_unt ON beers (name, unt_id)
Теперь код может вставлять данные без проверки, поэтому больше нет условия гонки. Но код должен обрабатывать ошибку, которая возникает, если пиво уже присутствует в таблице.
try:
cur.execute("""INSERT INTO beers (name, unt_id) VALUES (?, ?)""", ('IPA', 1))
conn.commit()
except sqlite3.IntegrityError:
conn.rollback()
print(f'Beer {name}-{unt_id} already exists!')
Комментарии:
1. Ваши последние пару строк кода (с некоторой настройкой), похоже, работают 🙂 Удивительно! Спасибо за объяснение и помощь мне 🙂