Могу ли я использовать оператор if для списка значений из SQLite?

#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. Ваши последние пару строк кода (с некоторой настройкой), похоже, работают 🙂 Удивительно! Спасибо за объяснение и помощь мне 🙂