【问题标题】:Can I use the same cursor while looping through it?我可以在循环时使用相同的光标吗?
【发布时间】:2014-01-07 21:16:44
【问题描述】:

我正在遍历 SELECT 结果,如下所示:

import MySQLdb

conn = MySQLdb.connect(host = 127.0.0.1, user = ...) # and so on
cur = conn.cursor()

cur.execute("SELECT * FROM some_table")

for row in cur:
    # some stuff I'm doing
    # sometimes I need to perform another SELECT here

问题是,我可以在for 循环内再次使用cur,还是必须创建另一个游标(甚至更多 - 另一个连接)?

我想我在这里缺少一些关于数据库或 Python 的基本知识......实际上我对这两者都很陌生。另外,我尝试用谷歌搜索答案失败了。

我什至会猜测自己我必须创建另一个光标,但我想我实际上已经像这样使用了一段时间,然后才意识到它可能是错误的并且它似乎有效。但我现在有点困惑,不能保证。所以我只是想确定一下。

【问题讨论】:

  • 您可以执行results = cur.execute(blah) 之类的操作,然后迭代results,然后重用光标。

标签: python mysql mysql-python database-cursor


【解决方案1】:

您必须创建一个新光标。否则,cur 现在将保存新“内部”选择的结果,而不是“外部”选择。

可能仍然有效,这取决于您的数据库库和您的运气,但您不应该指望它。我将在下面尝试解释。

不过,您不需要新的连接。

所以:

cur.execute("SELECT * FROM some_table")

for row in cur:
    # some stuff I'm doing
    inner_cur = conn.cursor()
    inner_cur.execute("SELECT * FROM other_table WHERE column = row[1]")
    for inner_row in inner_cur:
        # stuff

那么,为什么它有时会起作用?

好吧,让我们看看 for row in cur: 循环在幕后的真正作用:

temp_iter = iter(cur)
while True:
    try:
        row = next(temp_iter)
    except StopIteration:
        break
    # your code runs here

现在,iter(cur) 调用游标对象上的 __iter__ 方法。那有什么作用?这取决于cur,您的数据库库提供的游标类型的对象。

显而易见的实现是返回某种迭代器,该迭代器具有对游标对象或游标对象在幕后使用的同一行集合的引用。例如,当您在列表中调用 iter 时会发生这种情况。

但是没有什么要求数据库以这种方式实现其__iter__。它可以创建行集的副本以供迭代器使用。或者,更合理的说法是,它可以使迭代器引用当前行集……但是当您下次调用execute 时,将游标本身更改为引用一个不同的。如果它确实那个,那么旧的迭代器会继续读取旧的行集,你可以得到一个新的迭代器来迭代新的行集。

您不应该仅仅因为数据库库被允许这样做而依赖这种情况。当然,您也不应该依赖它不会发生。

更具体地说,想象一下这种类型:

class Cursor(object):
    # other stuff
    def __iter__(self):
        return iter(self.rowset)
    def execute(self, sql, *args):
        self.rowset = self.db.do_the_real_work(sql, *args)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-03
    • 2018-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-08
    • 1970-01-01
    相关资源
    最近更新 更多