2010-12-15 37 views
3

目前我有一個數據庫是不是由我管理,我不能做任何更改,id字段是一個smallint 2無符號,它可以給你多達65535 id條目。獲取未使用的下一個ID?

我的問題是,由於上述限制,我需要重新使用ID,我如何才能獲得下一個可用ID或者如何管理具有上述限制的插入?

回答

8

檢查1是免費的。如果不是:

SELECT MIN(a.id) + 1 AS smallestAvailableId 
FROM your_table AS a 
LEFT JOIN your_table AS a2 
     ON a2.id = a.id + 1 
WHERE a2.id IS NULL 
+0

真的很優雅。 – Konerak 2010-12-15 17:35:26

+2

如果數據庫爲空IFNULL(MIN(a.id)+ 1,1) – Prix 2010-12-15 18:26:02

+0

假設1如果不空閒則數據庫不爲空... – 2010-12-16 00:15:55

0

無論採用哪種方法都可能會因爲競爭條件而導致問題,除非您知道在任何時刻只有一個客戶端訪問數據庫。

要回答你的問題,你認爲什麼是「可用」的ID?請說明一下。直到所有的id已被使用一個簡單的

SELECT MAX(id) + 1 FROM table; 

應該做的。如果建立「可用」的ID,例如一個標準,重用那些被標記舊的所有ID,那麼你可以這樣做:

SELECT MIN(id) FROM table WHERE is_old = 1; 

然後,只需取消標記選定的ID。

+0

我最初的想法是保持注意maxId,因爲我不需要重複使用一個ID直到它達到極限65535,一旦max ID == 65535那麼我需要檢查一個未使用的ID – Prix 2010-12-15 17:35:11

+0

在這種情況下,「unused」可能意味着「沒有行存在這個值「,這就是爲什麼Alin的SELF-JOIN檢測NULL在這裏非常優雅。 – Konerak 2010-12-15 17:41:40

2

從標籤我推斷出你需要在Java中的id。

我個人會避免加入表格本身。由於您最多有64K行,因此我會將select id from table轉換爲Java並在Java中搜索id。搜索差距的一種方法是首先對數組進行排序(使用SQL或Java);找到差距就變得微不足道了。

如果您重複執行此操作,則可以緩存該數組並避免每次需要某個ID時都必須運行SQL語句。

無論你做什麼,如果有多個客戶端寫入數據庫,你必須準備好處理競爭條件,其中多個客戶端會嘗試使用相同的ID。您的代碼需要使用鎖定或能夠正常恢復以重新嘗試帶有不同ID的失敗插入(我假設在id列中存在唯一性約束)。

+1

+1注意競爭條件 – 2010-12-15 18:30:20

相關問題