Python SQLite3 UPDATE with tuple只使用最后一个值

2024-09-29 19:34:11 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图用一个大元组更新数据库中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”的现有值,如下所示:

^{pr2}$

然后我将元组转换为一个列表,这样我就可以在for f in db_framenum:循环中更改一些值,这将导致类似的元组:

[(0,), (1,), (2,) , ..., (108,)]

问题

到目前为止还不错,但是我尝试用这些新的framenum更新列'framenum':

c.executemany("UPDATE learnAlg SET framenum=?", (db_framenum_new))

我希望“framenum”列中的行具有新值,但它们都具有值:108(这是元组“db_framenum_new”)的最后一个值。为什么没有按顺序更新(从1到108)?在

期望:

framenum: 1, 2, .., 108

获得:

framenum: 108, 108, ..., 108
  • 注意:元组列表没有变长,只有某些值更改为。46以上的都有+1,54以上的都有+1(+2个总数)。。。在
  • 注2:列是用“framenum INTEGER”创建的。如果有问题的话,另一列有主键,用“framekanji-TEXT-PRIMARY-KEY”组成,它(目前)的值都是“NULL”。在

编辑

解决了我的问题,但我仍然对正确使用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]))

Tags: innewforexecutedbupdatechangefn
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))

我在这里稍微修改了结构;查询通过WHERE IN子句,仅将结果限制为change_numbers序列中的帧编号。我直接在光标上循环(不需要一次获取所有结果),并使用单独的UPDATEs来设置新的帧编号。我用enumerate()代替手动计数器来记录计数。在

如果需要按change_numbers对更新进行分组,那么只需告诉数据库执行这些更新:

^{pr2}$

从最高的帧编号开始,以避免更新之前已更新的帧编号。这假定您的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循环之外的之外!在

谢谢@Martijn Pieters,我需要使用rowid。这就是让它为我工作的代码:

c.execute("SELECT rowid, framenum FROM learnAlg")
db_framenum = c.fetchall()
print(db_framenum)

# How much v6 framenum differentiates from v4
change_fn = 0
for e, f in enumerate(db_framenum):
    e += 1
    db_framenum_new = f[1]
    if db_framenum_new in change_numbers:
        change_fn += 1
    db_framenum_new = db_framenum_new + change_fn

    c.execute("UPDATE learnAlg SET framenum=? WHERE rowid=?",
              (db_framenum_new, e))

但是我仍然不知道如何正确地使用c.executemany()。有关更新的问题,请参阅编辑。在

相关问题 更多 >

    热门问题