SQLite自动增量
1. 摘要
- AUTOINCREMENT关键字会增加额外的CPU、内存、磁盘空间和磁盘I/O开销,如果不是严格需要的话,应该避免使用。通常不需要。
- 在SQLite中,具有整数主键类型的列是ROWID(除在没有ROWID),它始终是一个64位有符号整数。
- 在.上插入,如果未显式地为ROWID或整数主键列指定值,则它将自动使用未使用的整数填充,通常比当前使用的最大的ROWID多一个。这是正确的,无论是否使用AUTOINCREMENT关键字。
- 如果AUTOINCREMENT关键字出现在整数主键之后,则更改自动ROWID分配算法,以防止ROWID在数据库生存期内重用。换句话说,AUTOINCREMENT的目的是防止ROWID从先前删除的行中重用。
2. 背景
在SQLite中,表行通常具有64位有符号整数。ROWID它在同一表中的所有行中都是唯一的。(没有ROWID(表是例外。)
您可以使用一个特殊的列名ROWID、_ROWID或OID来访问SQLite表的ROWID。除非您声明一个普通表列使用其中一个特殊名称,否则该名称的使用将引用声明的列,而不是内部ROWID。
如果表包含类型为整数主键,则该列成为ROWID的别名。然后,您可以使用四个不同的名称中的任意一个来访问ROWID,上面描述的原始的三个名称或给整数主键列。所有这些名称都是彼此的别名,在任何上下文中都同样有效。
当一个新行插入到SQLite表中时,ROWID可以指定为INSERT语句的一部分,也可以由数据库引擎自动分配。要手动指定ROWID,只需将其包含在要插入的值列表中即可。例如:
CREATE TABLE test1(a INT, b TEXT);
INSERT INTO test1(rowid, a, b) VALUES(123, 5, 'hello');
如果插入时没有指定ROWID,或者指定的ROWID值为NULL,则会自动创建适当的ROWID。通常的算法是给新创建的行一个ROWID,它比插入之前表中最大的ROWID大。如果表最初为空,则使用ROWID为1。如果最大的ROWID等于最大可能的整数(9223372036854775807),那么数据库引擎将开始随机选择正候选ROWID,直到找到以前没有使用的ROWID为止。如果经过合理次数的尝试后,无法找到未使用的ROWID,则插入操作将失败。SQLITE_FULL错误。如果没有显式插入负ROWID值,那么自动生成的ROWID值将始终大于零。
上面描述的普通ROWID选择算法将生成单调递增的唯一ROWID,只要您从不使用最大ROWID值,并且永远不会删除具有最大ROWID的表中的条目。如果删除行或创建具有最大可能ROWID的行,则可能在创建新行时重用先前删除的行中的ROWID,而新创建的ROWID可能没有严格的升序。
3. AUTOINCREMENT关键字
如果列的类型为整型主键AUTOINCREMENT,则使用略有不同的ROWID选择算法。为新行选择的ROWID至少比该表中以前存在的最大ROWID大一个。如果表以前从未包含任何数据,则使用ROWID为1。如果以前插入了最大可能的ROWID,则不允许新插入,任何插入新行的尝试都将失败,出现SQLITE_FLOLL错误。只考虑来自以前提交的事务的ROWID值。回滚的ROWID值被忽略,可以重用。
类保持最大ROWID的跟踪。内表命名“方形层序“.每当创建包含AUTOINCREMENT列的普通表时,sqlitSequence表都会自动创建和初始化。sqlitSequence表的内容可以使用普通UPDATE、INSERT和DELETE语句进行修改。但是对该表进行修改可能会扰乱AUTOINCREMENT密钥生成算法。请确保在进行此类更改之前知道正在做什么。sqlitSequence表不跟踪与UPDATE语句关联的ROWID更改,只跟踪INSERT语句。
AUTOINCREMENT关键字实现的行为与默认行为有细微差别。使用AUTOINCREMENT,自动选择ROWID的行保证具有以前从未被同一数据库中的同一表使用过的ROWID。并保证自动生成的ROWID是单调递增的。这些是某些应用中的重要特性。但是,如果您的应用程序不需要这些属性,您可能应该保持默认行为,因为AUTOINCREMENT的使用需要在插入每一行时完成额外的工作,从而导致插入运行稍微慢一些。
注意,“单调增加”并不意味着ROWID总是增加一个。一个是通常的增量。但是,如果插入由于(例如)唯一性约束而失败,则失败插入尝试的ROWID可能不会在后续插入中重用,从而导致ROWID序列中的空白。AUTOINCREMENT保证自动选择的ROWID将增加,但不会是顺序的。
因为AUTOINCREMENT关键字更改了ROWID选择算法的行为,所以不允许在没有ROWID表或除整数主键以外的任何表列上。控件上使用AUTOINCRENT的任何尝试没有ROWID表或整数主键列以外的列上的表将导致错误。