【问题标题】:Why is a second SQL statement breaking my loop?为什么第二条 SQL 语句会破坏我的循环?
【发布时间】:2014-11-25 12:50:09
【问题描述】:

我有一个包含一列文件名的 sqlite 表。有些文件名与其他文件重复,所以我想遍历每一行,在列中搜索类似条目,然后将这些结果打印到控制台。

print(row[0]) 表示我的findDupes 循环的前半部分有效,遍历每一行。当我创建另一个 sqlite 语句来查找类似条目并打印输出时,事情变得很奇怪。而不是继续循环,循环只打印第一个条目。

我不是 SQL 专家,所以不知道我做错了什么。任何帮助将不胜感激。谢谢!

def getFiles():
    dirs = os.listdir(path)
    for files in dirs:
        c.execute('INSERT INTO myTable(files) VALUES(?)', (files,))

def findDupes():
    row = c.execute('select files from myTable order by files')
    while True:
        row = c.fetchone()
        if row == None:
            break
        c.execute('select files from myTable where files like ?',(row[0]+'%',))
        dupe = c.fetchone()
        print (dupe[0])

【问题讨论】:

  • 您应该使用新光标进行第二次选择。
  • 要清楚,查看查询,您不仅会选择重复项,还会选择以该文件名作为前缀的任何内容。因此,如果您的表中有my_namemy_name1,当您调用查询select files from myTable where files like 'my_name%' 时,您将返回my_name1。我不确定您项目的目标是什么,但您应该注意这一点,以免给您带来更多问题。

标签: python sql sqlite


【解决方案1】:

首先,您的代码没有显示c 是什么——它是连接对象还是游标? (在这个对象中都可以使用,但游标通常更可取)为什么它是全局的?

假设它是一个游标对象,那么发生的事情是在您第一次通过循环时,对 c.execute 的第二次调用会重置查询,因此第二次调用 c.fetchone 时,sqlite 正在查看结果的select files from myTable where files like ?

解决这个问题的一种方法是使用多个游标;一种用于遍历文件名,另一种用于执行重复查找。

def findDupes(conn): #pass in your database connection object here
    file_curs = conn.cursor()
    file_curs.execute('select files from myTable order by files')
    while True:
        row = file_curs.fetchone()
        if row == None:
            break
        dup_curs = conn.cursor()
        dup_curs.execute('select files from myTable where files like ?',(row[0]+'%',))
        dupe = dup_curs.fetchone()
        print (dupe[0])

请注意,您可以完全在 SQL 中执行重复数据删除(例如,请参阅 Deleting duplicate rows from sqlite database),但如果您是 SQL 新手,则可能需要坚持上述方法。

【讨论】:

  • 我认为c 是光标,但从他的问题和您的回答中可以清楚地看出,它是连接对象。 +1
【解决方案2】:

您需要更改使用c 的方式。 findDupes() 中的循环第一次运行时,它会获取一行文件列表。之后,您将获得c.execute() 用于在循环的同一迭代中执行的相似选择。当第二次迭代发生时,第一个 c.fetchone() 正在从您的相似查询中获取一行,而不是您在循环外进行的原始所有文件按顺序查询。

对两个查询使用不同的变量或游标。

【讨论】:

    【解决方案3】:

    您的问题是,在您的循环中,您每次都调用row = c.fetchone(),这将从最近在 c 上执行的查询返回一行。在第二个循环中,这将是 c.execute('select files from myTable where files like ?',(row[0]+'%',)) 的结果,其中一行已经获取(所以你真的用当前代码将 row 设置为 c.execute('select files from myTable where files like ?',(row[0]+'%',)) 的第二个结果,我假设它可能返回 @987654325 @ 并打破你的循环)。

    试试这个:

    def findDupes():
        c.execute('select files from myTable order by files')
        rows = c.fetchall()
        for row in rows:
            c.execute('select files from myTable where files like ?',(row[0]+'%',))
            dupe = c.fetchone()
            print (dupe[0])
    

    【讨论】:

      【解决方案4】:

      您可以通过让数据库服务器为您进行计数来解决此问题。这样您只需运行一个查询,而不是通过获取所有文件然后逐一检查的低效方式:

      def find_dupes():
         rows = c.execute('SELECT files, COUNT(*) FROM myTable GROUP BY files HAVING COUNT(*) > 1')
         return [row[0] for row in rows]
      
      dupes = find_dupes()
      print('\n'.join(dupes))
      

      【讨论】:

      • 根据实际代码,结果实际上与查找完全重复的结果不同,它将是表中具有另一个文件作为前缀的任何文件(请参阅我对上面主要问题的评论) .但是对于纯粹的重复发现,我同意您的解决方案很棒!
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-03-14
      • 2011-12-28
      • 2014-08-23
      • 2020-10-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多