我正在尝试使用大元组更新数据库的1列的所有行。
c.execute("SELECT framenum FROM learnAlg")
db_framenum = c.fetchall()
print(db_framenum)
db_framenum_new = []
# How much v6 framenum differentiates from v4
change_fn = 0
for f in db_framenum:
t = f[0]
if t in change_numbers:
change_fn += 1
t = t + change_fn
db_framenum_new.append((t,))
print("")
print(db_framenum_new)
c.executemany("UPDATE learnAlg SET framenum=?", (db_framenum_new))
首先,我采用“framenum”列的现有值,如下所示:
[(0,), (1,), (2,) , ..., (104,)]
然后我将元组转换为列表,这样我就可以在for f in db_framenum:
循环中更改一些值,从而产生类似的元组:
[(0,), (1,), (2,) , ..., (108,)]
到目前为止一直很好,但后来我尝试使用这些新的framenumber更新列'framenum':
c.executemany("UPDATE learnAlg SET framenum=?", (db_framenum_new))
我希望列'framenum'中的行具有新值,但它们都具有值: 108 (这是元组'db_framenum_new'的最后一个值)。为什么他们没有按顺序更新(从1到108)?
期望值:
framenum: 1, 2, .., 108
GOT:
framenum: 108, 108, ..., 108
解决了我的问题,但我仍然对正确使用c.executemany()感兴趣。我不知道为什么这只会更新第一个rowid:
c.execute("SELECT rowid, framenum FROM learnAlg")
db_framenum = c.fetchall()
print(db_framenum)
db_framenum_new = []
# How much v6 framenum differentiates from v4
change_fn = 0
for e, f in enumerate(db_framenum):
e += 1
t = f[1]
if t in change_numbers:
change_fn += 1
t = t + change_fn
db_framenum_new.append((e,t))
print(db_framenum_new)
c.executemany("UPDATE learnAlg SET framenum=? WHERE rowid=?",
(db_framenum_new[1], db_framenum_new[0]))
答案 0 :(得分:2)
是的,您告诉数据库使用相同的framenum
更新所有行。那是因为UPDATE
语句没有选择任何特定的行。您需要告诉数据库一次更改一行,方法是为每个值包含一个主键。
由于您只是在改变特定的框架编号,因此您可以要求数据库仅提供这些特定的行而不是通过所有这些行。您可能还需要指定一个订单来更改数字;也许你需要在增加framenumber顺序时这样做?
c.execute("""
SELECT rowid, framenum FROM learnAlg
WHERE framenum in ({})
ORDER BY framenum
""".format(', '.join(['?'] * len(change_numbers))),
change_numbers)
update_cursor = conn.cursor()
for change, (rowid, f) in enumerate(c, 1):
update_cursor.execute("""
UPDATE learnAlg SET framenum=? WHERE rowid=?""",
(f + change, rowid))
我在那里稍微改变了结构;查询仅通过change_numbers
子句将结果限制为WHERE IN
序列中的帧编号。我直接循环游标(不需要一次获取所有结果)并使用单独的UPDATE
来设置新的帧编号。我使用enumerate()
代替手动计数器来为我计算。
如果您需要按change_numbers
分组更新,那么只需告诉数据库执行这些更新:
change = len(change_numbers)
for framenumber in reversed(change_numbers):
update_cursor.execute("""
UPDATE learnAlg SET framenum=framenum + ? WHERE framenum=?
""", (change, framenumber))
change -= 1
这从最高框架编号开始,以避免更新之前已更新的框架编号。这假设您的change_numbers
按递增顺序排序。
您的executemany
更新应该只传入整个列表,而不仅仅是前两个项目;你需要改变你追加价值的方式:
for e, f in enumerate(db_framenum):
# ...
db_framenum_new.append((t, e)) # framenum first, then rowid
c.executemany("UPDATE learnAlg SET framenum=? WHERE rowid=?",
db_framenum_new)
请注意,executemany()
调用是在外部 for
循环进行的!