2010-05-13 51 views
3

我想刪除除了列表中的記錄ID之外的所有記錄。該列表的長度可以有所不同,可以很容易地包含2000+的ID,...刪除除了我在Python列表中的ID以外的所有記錄

目前,我將我的列表轉換爲一個字符串,所以它適合於這樣的事情: cursor.execute(「」「從表中刪除編號不在(%s)「」「,(列表)) 這感覺不對,我不知道列表允許多長時間,...

什麼是最有效的方式這來自python?

用額外的字段來改變表格的結構來標記/取消標記刪除記錄將是很好的,但不是一個選項。 有一個專用的表存儲ID的確會很有幫助,那麼這可以通過一個SQL查詢來完成......但我真的想盡量避免這些選項。

感謝,

+0

看到這個問題關於最大列表長度:http://stackoverflow.com/questions/855191/how-big-can-a-python-array-get/855455#855455 – 2010-05-13 11:41:09

+2

我認爲更相關的限制將是MySQL端,在'NOT IN'參數字符串中。 – Amber 2010-05-13 11:45:08

回答

1

你有沒有用盡SQL直接做你計算的可能性?如果是這樣,我沒有看到另一種方式來做到這一點,而不做你已經做的事情。可以肯定,當然,要創建有效的SQL,如果你在插上其中:

','.join(str(int(x)) for x in ids) 

你肯定是,如果直接取代你的說法。我不確定是否對NOT IN(...)子句中的ids數量有限制,但是會懷疑它,因爲在使用子查詢填充該列表時可以使用任意長的列表。

+0

是的,這是我在這一刻做的。我想最好的解決辦法是有一些臨時或專用的表。 – 2010-05-13 19:14:00

3

如果db表不是太大,只是在所有的ID讀取,並 讓你想刪除的人的名單:

keep_ids=[...] 
cursor.execute('SELECT id FROM table') 
delete_ids=[] 
for (row_id,) in cursor: 
    if row_id not in keep_ids: 
     delete_ids.append(row_id) 
cursor.executemany('DELETE FROM table WHERE id = %s',delete_ids) 

如果db表是巨大的,然後重新創建表:

keep_ids=[...] 
cursor.execute('CREATE TABLE IF NOT EXISTS temp_table LIKE table') 
cursor.executemany('INSERT INTO temp_table (SELECT * FROM table WHERE id = %s)',keep_ids) 
cursor.execute('DROP TABLE table') 
cursor.execute('ALTER TABLE temp_table RENAME table') 
+0

有趣的想法,我會試驗。 – 2010-05-13 19:15:52

-2

這就是temporary tables的用途。您創建一個包含排除列表的臨時表並使用DBM爲您做出選擇。一個簡單的例子:

CREATE TABLE words (id integer primary key not null, word string); 
CREATE TEMPORARY TABLE exclusion (word string); 
INSERT INTO words VALUES ... # 100,000 of these 
INSERT INTO exclusion VALUES ... # 1000 of these 
DELETE FROM words WHERE words.word NOT IN (SELECT word FROM exclusion); 
# 99,000 records now in words, table exclusion evaporates when the session is over 

有人誰真正知道SQL可能可以改善我的最後一行。如果您在應用程序空間中進行選擇,則會出現問題。 MySQL具有臨時表,但即使您沒有創建/刪除排除項仍然會比過長的聲明更好。

順便說一下,我在Python中黑掉了,只是因爲我有一個很大的單詞表。代碼很無聊,所以沒有發佈。

+0

100,000個插入的延遲不會比具有100,000個ID的單個查詢更糟嗎? – apg 2010-05-13 13:21:12

+0

不知道,整個事情在我的蹩腳的桌面上花了幾秒鐘,這個問題也預設了數據庫中已經存在table'words' – msw 2010-05-13 13:27:30

0

我想添加一個「todelete tinyint(1)not null default 1」列到表中,將它更新爲0以保留那些必須保留的id,然後delete from table where todelete;。它快於不在。

或者,創建一個與您的結構相同的表,將保留的行插入並重命名錶。然後,放棄舊的。

相關問題