2014-09-30 121 views
0

我有一個包含一列文件名的sqlite表。一些文件名是其他文件的副本,所以我想遍歷每一行,在列中搜索相似的條目,然後將這些結果打印到控制檯。爲什麼第二個SQL語句會打破我的循環?

A 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]) 
+0

你應該用你的第二個選擇新的光標。 – 2014-09-30 19:32:04

+0

要清楚,查看查詢,您不僅可以選擇重複項,而且還可以選擇以該文件名作爲前綴的任何項。因此,如果你的表中有'my_name'和'my_name1',當你調用查詢'從myTable中選擇文件'my_name%'' '時,你將返回'my_name1'。我不確定你的項目的目標是什麼,但你應該意識到這一點,以免它給你帶來更多的問題。 – JB333 2014-09-30 20:11:07

回答

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,你可能要堅持上述。

+0

我假設'c'是遊標,但是從他的問題和答案中可以清楚地看到,它是連接對象。 +1 – aneroid 2014-09-30 20:03:46

1

你的問題是,你的循環中你每一次,它會返回一個排從最近查詢的執行基於C調用row = c.fetchone()。在第二個循環中,這將是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]) 
+0

+1。我的手機輸入得太慢了。 – aneroid 2014-09-30 19:48:11

1

你將需要改變你如何使用c。第一次運行findDupes()循環時,它將取出一行文件列表。在那之後,你會得到c.execute()的相似性選擇在循環的相同迭代中執行。當第二次迭代發生時,第一個從您的相似性查詢中獲取一行,而不是您在循環外部獲得的原始全文件順序查詢。

對這兩個查詢使用不同的變量或遊標。

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

根據實際代碼,結果實際上與查找確切的重複項不同,它將是表中有另一個文件作爲前綴的任何文件(請參閱我對上面主要問題的評論)。但對於純粹的重複查找,我同意你的解決方案非常棒! – JB333 2014-09-30 20:15:49

相關問題