我可以在SQLite的值列表中使用if语句吗



我想写一段代码,从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()

这似乎不起作用,因为啤酒一直在添加,即使它已经在列表中多次添加。那么,我如何更改此代码以使其工作呢?

问题中的代码看起来就像是查询了数据库表,现在检查每一行,看看它是否与啤酒的详细信息匹配。除了打字之外,这不太可能奏效,因为如果任何行与啤酒不匹配,就会插入新的啤酒行。

假设表格看起来有点像这样:

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()

这运行得很好,但如果有多个人在运行该程序,则可能会通过在查询和插入之间插入来添加重复的啤酒(这被称为竞争条件(。我们可以通过向表中添加约束来防止这种情况,要求nameunt_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!')

最新更新