sqlite 主键
- 除WITHOUT ROWID表外,SQLite表中的所有行都有一个64位有符号整数键,用于唯一标识其表中的行。这个整数通常称为rowid。WITHOUT ROWID表仅在SQLite版本3.8.2之后可用。
- INTEGER PRIMARY KEY ,只有INTEGER 修饰主键,那么该列才是rowid的别名。其他整数类型名称(如 INT 或 BIGINT 或 SHORT INTEGER 或 UNSIGNED INTEGER )会使主键列表现为具有整数关联和唯一索引的 普通表列,而不是 rowid 的别名。如果不是真正的主键,PRIMARY KEY 的列允许为NULL,但这违反了所有SQL标准。
- 通过rowid访问记录是高度优化和非常快速的。
- 应用程序通常不应直接访问rowid,而是使用INTEGER PRIMARY KEY。如果rowid没有INTEGER PRIMARY KEY的别名,那么它不是持久性的,可能会改变。特别是VACUUM命令将更改未声明INTEGER PRIMARY KEY的表的rowid
- 例外:如果声明类型为INTEGER的列的声明包含PRIMARY KEY DESC子句,则它不会成为rowid的别名,也不会被归类为整数主键。** It is due to a bug in early versions of SQLite.** 下面代码 x就是rowid的别名
CREATE TABLE t(x INTEGER PRIMARY KEY ASC, y, z);
CREATE TABLE t(x INTEGER, y, z, PRIMARY KEY(x ASC));
CREATE TABLE t(x INTEGER, y, z, PRIMARY KEY(x DESC));
下面代码 x不是rowid的别名
CREATE TABLE t(x INTEGER PRIMARY KEY DESC, y, z);
- 使用WITHOUT ROWID。可以省略rowid,有时有空间和性能优势。
CREATE TABLE IF NOT EXISTS wordcount(
word TEXT PRIMARY KEY,
cnt INTEGER
) WITHOUT ROWID;
- 每个 WITHOUT ROWID 表都必须有一个 PRIMARY KEY。如果带有 WITHOUT ROWID 子句的 CREATE TABLE 语句缺少 PRIMARY KEY ,则会引发错误。
- 在大多数情况下,普通表的特殊 rowid 列也可以称为 oid或 _rowid _。但是,只有 rowid 作为CREATE TABLE语句中的关键字。
- 在底层文件格式中,每个rowid都存储为可变长度整数。这意味着小的非负rowid值比大rowid或负rowid值占用更少的磁盘空间。
- 上面的所有复杂问题(以及此处未提及的其他复杂问题)都源于需要保留数百亿个SQLite数据库文件的向后兼容性。在一个完美的世界中,不存在“rowid”这样的东西,并且所有表都遵循实现为WITHOUT ROWID表的标准语义,只是没有“WITHOUT ROWID”关键字。不幸的是,生活很混乱。 SQLite的设计师为当前的烂摊子提供了真诚的道歉。
引用
[1]: https://www.sqlite.org/withoutrowid.html#differences_from_ordinary_rowid_tables
[2]: https://www.sqlite.org/lang_createtable.html#rowid
[3]: https://www.sqlite.org/rowidtable.html