【发布时间】:2013-12-13 05:39:08
【问题描述】:
在使用 SQLite 创建一个小应用程序时,我注意到一个奇怪的事情(对我来说)自动增量列计数器算法行为。
例如,让我们尝试使用以下架构创建数据库
CREATE TABLE numbers (num INTEGER UNIQUE ON CONFLICT IGNORE);
和一个小的 Python 脚本
import sqlite3
con = sqlite3.connect('db.sqlite3')
cur = con.cursor()
def values():
for i in xrange(1, 3):
yield (i,)
try:
cur.executemany('INSERT INTO numbers (num) VALUES (?)', values())
except sqlite3.DatabaseError, err:
print u'Error: ', err
else:
con.commit()
print u'Number of added rows: %d' % cur.rowcount
cur.close()
con.close()
让我们运行 3 次脚本。上次使用不同的 values() 输出,例如 xrange(3,5)。所以,我们得到输出
Number of added rows: 2
Number of added rows: 0
Number of added rows: 2
好的,那么让我们检查一下我们的数据库,一切看起来都正常
$ sqlite3 db.sqlite3 'select rowid, * from numbers'
1|1
2|2
3|3
4|4
然后尝试通过向系统 rowid 列添加自动增量别名来创建数据库。
CREATE TABLE numbers (id INTEGER PRIMARY KEY AUTOINCREMENT, num INTEGER UNIQUE ON CONFLICT IGNORE);
然后执行与上面相同的操作并检查行。
$ sqlite3 db.sqlite3 'select rowid, * from numbers'
1|1|1
2|2|2
5|5|3 <- sqlite jumped over intermediate counter values for rowid and id column
6|6|4
当对表使用 IGNORE 约束破坏解析算法时,SQLite 保存 rowid 和别名自动增量列的中间计数器值,并在分配新的自动增量值时跳过它们。为什么?
【问题讨论】: