为什么第二个SQL语句会破坏我的循环?

时间:2014-09-30 19:23:09

标签: python sql sqlite

我有一个包含一列文件名的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])

4 个答案:

答案 0 :(得分:2)

首先,您的代码没有透露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新手,则可能需要坚持使用上述内容。

答案 1 :(得分:1)

您的问题是,在您的循环中,您每次都会调用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]+'%',))的第二个结果,我假设可能会返回None并打破你的循环。

试试这个:

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])

答案 2 :(得分:1)

您需要更改使用c的方式。第一次在findDupes()中运行循环时,它会获取一行文件列表。在那之后,你已经有了c.execute()的同类选择在循环的同一次迭代中执行。当第二次迭代发生时,第一个c.fetchone()从你喜欢的查询中获取一行,而不是你在循环之外的原始所有逐个文件查询。

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

答案 3 :(得分:0)

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

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))