SQLite AUTOINCREMENT你需要懂得知識
1. 總結
- AUTOINCREMENT關鍵字會占用額外的CPU,內存,磁盤空間和磁盤I / O開銷,如果不是嚴格需要,應該避免使用。通常情況下,是不需要它。
- 在SQLite中,類型為INTEGER PRIMARY KEY的列是ROWID的別名 (WITHOUT ROWID表除外),它始終是64位有符號整數。
- 在INSERT上,如果未明確給出ROWID或INTEGER PRIMARY KEY列的值,則它將自動填充未使用的整數,通常比當前使用的最大ROWID多一個。無論是否使用AUTOINCREMENT關鍵字,都是如此。
- 如果AUTOINCREMENT關鍵字出現在INTEGER PRIMARY KEY之后,則會更改自動ROWID分配算法,以防止在數據庫的生命周期內重用ROWID。換句話說,AUTOINCREMENT的目的是防止從先前刪除的行重用ROWID。
2. 背景
在SQLite中,表行通常具有64位有符號整數ROWID ,它在同一個表中的所有行中是唯一的。(沒有ROWID表是例外。)
你可以使用特殊列名稱ROWID,_ROWID_或OID之一,來訪問SQLite表的ROWID。除非你聲明普通表列使用其中一個特殊名稱,否則使用該名稱將引用聲明的列而不是內部ROWID。
如果表包含INTEGER PRIMARY KEY類型的列,則該列將成為ROWID的別名。然后,您可以使用四個不同的名稱中的任何一個來訪問ROWID,上面描述的原始三個名稱或給予INTEGER PRIMARY KEY列的名稱。所有這些名稱都是彼此的別名,并且在任何情況下都能同樣有效。
將新行插入SQLite表時,可以將ROWID指定為INSERT語句的一部分,也可以由數據庫引擎自動指定。要手動指定ROWID,只需將其包含在要插入的值列表中即可。例如:
- CREATE TABLE test1(INT,b TEXT);
- INSERT INTO test1(rowid,a,b)VALUES(123,5,'hello');
如果在插入上未指定ROWID,或者指定的ROWID的值為NULL,則會自動創建適當的ROWID。通常的算法是為新創建的行提供一個ROWID,該ROWID比插入前表中的最大ROWID大一個。如果表最初為空,則使用ROWID為1。如果最大的ROWID等于最大可能的整數(9223372036854775807),則數據庫引擎隨機開始隨機選擇正候選ROWID,直到找到之前未使用過的ROWID。如果在合理的嘗試次數后找不到未使用的ROWID,則插入操作將失敗,并顯示SQLITE_FULL錯誤。如果未顯式插入負ROWID值,則自動生成的ROWID值將始終大于零。
只要你從不使用最大ROWID值,而且不刪除具有最大ROWID的表中的條目,上述常規ROWID選擇算法將生成單調遞增的唯一ROWID。如果您刪除行或者創建了具有最大可能ROWID的行,則在創建新行時可能會重復使用先前刪除的行中的ROWID,并且新創建的ROWID可能不會嚴格按升序排列。
3. AUTOINCREMENT關鍵字
如果列的類型為INTEGER PRIMARY KEY AUTOINCREMENT,則使用稍微不同的ROWID選擇算法。為新行選擇的ROWID至少比同一個表中以前存在的最大ROWID大一個。如果表之前從未包含任何數據,則使用ROWID為1。如果先前已插入最大可能的ROWID,則不允許新的INSERT,并且任何插入新行的嘗試都將失敗,并出現SQLITE_FULL錯誤。僅考慮已提交的先前事務中的ROWID值。回滾的ROWID值將被忽略,可以重復使用。
SQLite內部使用名為“ sqlite_sequence ” 的內部表跟蹤最大的ROWID 。每當創建包含AUTOINCREMENT列的普通表時,都會自動創建并初始化sqlite_sequence表。可以使用普通的UPDATE,INSERT和DELETE語句修改sqlite_sequence表的內容。但是對此表進行修改可能會擾亂AUTOINCREMENT密鑰生成算法。在進行此類更改之前,請確保你知道自己在做什么。sqlite_sequence表不跟蹤與UPDATE語句關聯的ROWID更改,僅跟蹤INSERT語句。
AUTOINCREMENT關鍵字實現的行為與默認行為略有不同。使用AUTOINCREMENT,具有自動選擇的ROWID的行可以保證具有以前從未在同一數據庫中使用同一個表的ROWID。并且自動生成的ROWID保證單調遞增。這些是某些應用中的重要屬性。但是,如果你的應用程序不需要這些屬性,應該保持默認行為,因為使用AUTOINCREMENT需要在插入每一行時執行其他工作,從而導致INSERT運行速度稍慢。
請注意,“單調增加”并不意味著ROWID總是增加一個。一個是通常的增量。但是,如果插入因(例如)唯一性約束而失敗,則失敗的插入嘗試的ROWID可能不會在后續插入中重用,從而導致ROWID序列中出現間隙。AUTOINCREMENT保證自動選擇的ROWID將增加但不是它們將是連續的。
由于AUTOINCREMENT關鍵字更改了ROWID選擇算法的行為,因此不允許在WITHOUT ROWID表或INTEGER PRIMARY KEY以外的任何表列上使用AUTOINCREMENT 。任何在WITHOUT ROWID表或INTEGER PRIMARY KEY列以外的列上使用AUTOINCREMENT的嘗試都會導致錯誤。