删除行后的sqlite rowid

删除行后的sqlite rowid,sqlite,Sqlite,我创建了带有列id、名称的sqlite表tmp CREATE TABLE if not exists tmp ( id INTEGER PRIMARY KEY, name TEXT NOT NULL); 我在其中插入了5行 当我使用rowid列运行select查询时,它会给出下面的输出 select rowid,id,name from tmp; rowid id name 1 1

我创建了带有列id、名称的sqlite表tmp

CREATE TABLE if not exists tmp (
            id             INTEGER PRIMARY KEY,
            name            TEXT NOT NULL);
我在其中插入了5行

当我使用rowid列运行select查询时,它会给出下面的输出

select rowid,id,name from tmp;

rowid  id    name
1      1     a
2      2     b
3      3     c
4      4     d
5      5     e
现在我删除id为3和4的行,并再次运行上面的查询

rowid  id    name
1      1     a
2      2     b
5      5     e
DELETE FROM tmp WHERE rowid = 3;
DELETE FROM tmp WHERE rowid = 4;
select rowid,* from tmp;
rowid  my_i    name
1      1        a
2      2        b
5      5        e
现在我的问题是rowid没有得到重置和孔

即使在抽真空后,它仍然不会重置rowid,它仍然给出上述输出

我想要的输出是

rowid id  name
1      1  a
2      2  b
3      5  e
有人能帮我达到以上的产量吗


谢谢

我想您已经对rowid了解了一点,因为您正在询问它与VACUUM命令的交互,但这对于未来的读者来说可能是有用的信息:

rowid是由sqlite内部使用的,除非您在不使用rowid的情况下使用。一个真空应该重建表,目的是减少数据库文件中的碎片,以及。继续

以下是你问题的答案:罗维德真的很特别。非常特殊,如果您有一个整数主键,它将成为rowid列的别名。从以下文件:

除了下面提到的一个例外,如果rowid表的主键由单个列组成,并且该列的声明类型在任何大小写混合中都是整数,则该列将成为rowid的别名。这样的列通常称为整数主键。仅当声明的类型名称为整数时,主键列才成为整数主键。其他整数类型名称(如INT或BIGINT、SHORT integer或UNSIGNED integer)会导致主键列作为具有整数相关性和唯一索引的普通表列,而不是rowid的别名

这会使您的主键比其他情况下更快,这大概是因为没有从主键到rowid的查找:

rowid表的数据存储为B树结构,每个表行包含一个条目,使用rowid值作为键。这意味着按rowid检索或排序记录很快。搜索具有特定rowid的记录或具有指定范围内rowid的所有记录的速度大约是通过指定任何其他主键或索引值进行类似搜索的两倍

当然,当您的主键是rowid的别名时,如果这种情况发生变化,将非常不方便。由于rowid现在已被化名为应用程序数据,因此sqlite不允许更改它

因此,本手册中有一个小注释:

VACUUM命令可以更改任何表中没有显式整数主键的项的rowid

如果你真的需要在真空状态下更改rowid,我不明白为什么-请在评论中自由讨论你的原因,我可能有一些建议,你可以避免这种别名行为。请注意,它将降低使用主键进行任何表查找的性能

为了避免别名并降低性能,在定义密钥时可以使用INT而不是INTEGER:

仅当声明的类型名称为整数时,主键列才成为整数主键。其他整数类型名称(如INT或BIGINT、SHORT integer或UNSIGNED integer)会导致主键列作为具有整数相关性和唯一索引的普通表列,而不是rowid的别名


我为一些案件找到了解决办法。我不知道为什么,但这奏效了。 1.将列id重命名为非主键的任何其他名称,或删除此列,因为您已经具有rowid

CREATE TABLE if not exists tmp (
            my_i             INTEGER NOT NULL,
            name            TEXT NOT NULL);
2.在其中插入5行

从tmp中选择rowid,*

rowid  my_i    name
1      1      a
2      2      b
3      3      c
4      4      d
5      5      e
3.删除行ID为3和4的行,然后再次运行上面的查询

rowid  id    name
1      1     a
2      2     b
5      5     e
DELETE FROM tmp WHERE rowid = 3;
DELETE FROM tmp WHERE rowid = 4;
select rowid,* from tmp;
rowid  my_i    name
1      1        a
2      2        b
5      5        e
4.运行SQL

VACUUM;
5.运行SQL

select rowid,* from tmp;
输出:

rowid my_i  name
1      1    a
2      2    b
3      5    e

必须将数据库中的所有数据定义到新的数组/列表中。然后必须删除表并将所有数据从数组/列表重写到数据库中。 检查它


ID的用途是标识一行。当你改变ID的时候,这就不可能了。实际上我并不热衷于运行真空系统,但正如一些博客所说,我尝试了真空系统。正如我在问题中提到的,我只希望最终输出带有新的rowid。不管我是用吸尘器还是其他方法。除了将列类型更改为INT之外,您知道其他实现方法吗?但是为什么需要更改id:s?我不明白为什么这对你有用。我需要旧id到新id的映射。所以在删除之后,我想重新生成行ID。在这之后,行id将是没有漏洞的新id,旧id将在实际id列中,然后只需执行查询,按id ASC排序,并在Java端对结果进行循环时使用您自己的计数器以获得序号。仍然不知道你为什么需要它-似乎持久的id:s比让它们四处移动要好…我可以做到。但我只需要在其他查询中使用新旧id映射,而不需要在代码中使用。