首页 > 解决方案 > SQLite:PRIMARY KEY 默认为 ASC 吗?

问题描述

即,以下两个 SQL 语句在 SQLite 中是否等效?

CREATE TABLE posts (
  id INTEGER PRIMARY KEY
);

CREATE TABLE posts (
  id INTEGER PRIMARY KEY ASC
);

标签: sqlite

解决方案


的,他们是。

无需指定ASC请注意,如果您要指定DESC,则NO它们不等效(请参见下面的4),因为id INTEGER PRIMARY KEY DESC该列是rowid列的别名的排除项: -

上面提到的例外情况是,如果声明类型为“INTEGER”的列的声明中包含“PRIMARY KEY DESC”子句,则它不会成为rowid 的别名,也不会被归类为整数主键。这个怪癖不是设计使然。这是由于 SQLite 早期版本中的一个错误造成的。但是修复错误可能会导致向后不兼容。因此,原始行为已被保留(并记录在案),因为极端情况下的奇怪行为比兼容性中断要好得多。

ROWID 和整数主键

您可以使用id INTEGER, PRIMARY KEY(id, DESC),但在检索列时仍默认为 ASC,因为它是 rowid 的别名(参见下面的5

也许考虑以下几点:-

DROP TABLE IF EXISTS posts1;
CREATE TABLE posts1 (
  id INTEGER PRIMARY KEY
);

DROP TABLE IF EXISTS posts2;
CREATE TABLE posts2 (
  id INTEGER PRIMARY KEY ASC
);

DROP TABLE IF EXISTS posts3;
CREATE TABLE posts3 (
  id INTEGER PRIMARY KEY DESC
);

DROP TABLE IF EXISTS posts4;
CREATE TABLE posts4 (
    id INTEGER, PRIMARY KEY (id DESC)
);

INSERT INTO posts1 VALUES(null),(null),(null);
INSERT INTO posts2 VALUES(null),(null),(null);
INSERT INTO posts3 VALUES(null),(null),(null);
INSERT INTO posts4 VALUES(null),(null),(null);

SELECT * FROM sqlite_master WHERE name LIKE '%posts%';

SELECT * FROM posts1;
SELECT * FROM posts2;
SELECT * FROM posts3;
SELECT * FROM posts4;

结果

1

查询SELECT * FROM sqlite_master WHERE name LIKE '%posts%';结果:-

在此处输入图像描述

如您所见,由于已创建索引sqlite_autoindex_posts3_1 , posts3明显不同

其他没有创建特定索引,因为 id 列是rowid列的别名

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

ROWID 和整数主键

2

查询SELECT * FROM posts1;结果:-

在此处输入图像描述

3

查询SELECT * FROM posts2;,按照以下方式确认最初的“是”答案:-

在此处输入图像描述

4

查询SELECT * FROM posts3;,可能有点混乱,但表明id INTEGER PRIMARY KEY DESC不会导致rowid的别名,并且在没有值或 null 插入列的情况下,该值是 null 而不是自动生成的值。不存在 UNIQUE 约束冲突(因为空值被视为不同的值)。

在此处输入图像描述

5

SELECT * FROM posts4;即使使用了查询,查询也会产生与 1 和 2 相同的结果id INTEGER, PRIMARY KEY (id DESC)。确认即使通过列定义应用DESC ,排序顺序仍默认为ASC(除非使用 ORDER BY 子句)。

  • 请注意,此特性特定于rowid列或其别名。

在此处输入图像描述


推荐阅读