我想预测(真正反向工程)sqlite表中任何要插入的行的rowid(使用某些表的rowid重构sqlite插入流作为其他表中的外键)。插入可以在任意插入和删除序列之后发生。如何在插入时由sqlite确定rowid?
这是一个不断递增的反击吗?
int64_t next_rowid() {
static int64_t r = 0;
return ++r;
}
也许最小的一排没有使用?
// Algorithm description, not (likely) working code
static sorted_set<int64_t> deleted;
static int64_t top = 0;
int64_t next_rowid() {
if(deleted.size()==0) deleted.push(++top);
return deleted.pop_front();
}
void delete_rowid(int64_t r) {
deleted.push(r);
}
其他一些方案?
未指定?
https://sqlite.org/autoinc.html -
SQLite是单线程,所以在大多数情况下它执行select max(id) +1 from the_table
。从这个角度来看,很难说出序列是什么。但是,您可以提供有效的序列威胁删除的东西,因为不存在。或许我错过了一些东西。
正如CL发现的那样。 Autoincrement
以更稳定的方式工作。所以你不能两次得到相同的id。从中可以看出,同时删除了某些内容......
首先,有两种类型的rowid确定算法。取决于是否指定了AUTOINCREMENT
。
AUTOINCREMENT
意味着rowid保证在数量大小的限制范围内增加(9223372036854775807)。如果达到该数字,则任何后续插入尝试都将失败,并出现SQLITE_FULL异常。
在上述场景中没有AUTOINCREMENT
,算法将尝试找到未使用的rowid,因此得到的rowid可能低于其他现有rowid。
这两种算法都没有保证增加1,而通常它们会增加1。
AUTOINCREMENT
导致创建一个sqlite_sequence表,最后使用的rowid保存在序列列中,注意!它可以被操纵/改变,所以添加1条记录然后将其更改为100,下一次插入可能是101。
name列是该行所用表的名称。
因此,算法似乎是这样的:
AUTOINCREMENT
的地方
1大于插入行的表中的最高rowid,除非它大于9223372036854775807,在这种情况下将寻找未使用的rowid。