Python SQLite3 / Nested cursor.execute

时间:2018-04-28 10:08:09

标签: python sqlite nested cursor execute

考虑以下这段代码:

for count in range(28, -1, -1):
    crsr.execute("SELECT board, win1, win2 FROM positions WHERE balls = ?", (count,))
    response = crsr.fetchall()
    print count, len(response)
    for possibility in response:
        internal = possibility[0]
        player = count & 1
        victor = 1 - player
        opponent = 2 - player
        victory = possibility[opponent]
        if victory:
            crsr.execute("UPDATE positions SET result = ? WHERE board = ?", (victor, internal))
        else:
            subsequent = derive((internal, count))
            for derived in subsequent:
                external = reduce(derived[0])
                crsr.execute("SELECT result FROM positions WHERE board = ?", (external,))
                colour = crsr.fetchall()
                if colour[0][0] == player:
                    victor = player
                    break
            crsr.execute("UPDATE positions SET result = ? WHERE board = ?", (victor, internal))

考虑一下:

response = crsr.fetchall()

每当response中有多达10个 7 行时,上述语句就会返回内存错误,即使在具有8 GB RAM的系统上也是如此。

所以,我决定用以下代码改变:

for count in range(28, -1, -1):
    crsr.execute("SELECT board, win1, win2 FROM positions WHERE balls = ?", (count,))
    response = crsr.fetchall()
    print count, len(response)
    for possibility in response:
        internal = possibility[0]

为:

for count in range(28, -1, -1):
    crsr.execute("SELECT COUNT(board) FROM positions WHERE balls = ?", (count,))
    sum = crsr.fetchall()
    total = sum[0][0]
    print count, total
    crsr.execute("SELECT board, win1, win2 FROM positions WHERE balls = ?", (count,))
    for possibility in range(total):
        response = crsr.fetchone()
        internal = response[0]

现在就行:

response = crsr.fetchone()

利用crsr变量为possibilityrange(total)的每次迭代执行SQLite3选择查询。

在'for'循环中已经存在其他crsr个语句:

crsr.execute("UPDATE positions SET result = ? WHERE board = ?", (victor, internal))

该声明发生两次,

crsr.execute("SELECT result FROM positions WHERE board = ?", (external,))

该声明发生一次。

因此,只要crsr行中的response = crsr.fetchall()变量随着possibilityrange(total)的每次迭代而变化,它就不会与其他crsr冲突}语句已经在同一个'for'循环中?

我们无法使用其他游标变量创建用于执行不同的SQLite3查询,因为crsr是通过使用crsr = connection.cursor()为特定数据库文件定义的,只要它被初始化(以spline.db为准),这个特例)。

所以,我想知道,如果有任何其他替代解决方案可供选择,那么非常有效。

1 个答案:

答案 0 :(得分:1)

结果集是游标对象的一部分,因此无论何时调用execute(),都会中止对同一游标对象的任何先前查询。避免这种情况的唯一方法是在执行下一个查询之前使用fetchall()读取所有结果行。

为了能够执行多个同时查询,您必须使用多个游标。只需多次致电connection.cursor()

请注意,您不得修改您仍在阅读的表格(即使您使用的是多个游标);读取光标可能会跳过或读取两次更改的行。如果您无法使用fetchall(),请将第一个查询的结果放入临时表中:

crsr1.execute("CREATE TEMP TABLE temp_pos(board, win1, win2)")

for count in ...:
    crsr1.execute("INSERT INTO temp_pos SELECT board, win1, win2 ...")

    crsr1.execute("SELECT board, win1, win2 FROM temp_pos")
    for row in crsr1:
        if ...:
            crsr2.execute("UPDATE positions ...")
        else:
            crsr2.execute("SELECT ... FROM positions ...")
            ...
    crsr1.execute("DELETE FROM temp_pos")

crsr1.execute("DROP TABLE temp_pos")
相关问题