表级别定义的PRIMARY KEY约束是否保证AUTOINCREMENT并且没有值重用?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (1)
  • 关注 (0)
  • 查看 (82)

请考虑以下表定义:

CREATE TABLE names (
    id INTEGER,
    name TEXT NOT NULL,
    PRIMARY KEY (id)
)

它是否保证id每个新插入都会自动递增,并且删除行的值不会被重用?

我查阅了Sqlite3的文档,但找不到答案。

提问于
用户回答回答于

id INTEGER PRIMARY KEY 在它自己的保证(需要)一个唯一的整数值,并且如果没有专门分配值将提供一个,直到最高值达到64位有符号整数(9223372036854775807)的最高允许值,之后可以找到并应用未使用的值。

随着AUTOINCREMENT有保证(如果不是回避)总是提供更高的价值,但如果9223372036854775807达到的,而不是分配一个未使用的数量将导致一个SQLITE_FULL错误。这是唯一的区别,从分配的数字的角度来看。

两者都不能保证单调增加的价值。

没有AUTOINCREMENT,计算/算法相当于

  • 1 + max(rowid),如果该值大于9223372036854775807,则尝试查找未使用且因此值较低的值。
    • 我没有看到任何人遇到过未分配随机未使用值的情况。

使用AUTOINCREMENT,计算/算法是

  • 1 + max(rowid)或SELECT seq FROM sqlite_sequence中的较大者WHERE name ='the_table_name_the_rowid_is_being_assigned_to',如果该值大于9223372036854775807则为SQLITE_FULL ERROR。
  • 注意,无论哪种方式,最大rowid可能是最终没有插入的行,因此可能存在间隙。

答案可能是最好的:最好/建议仅将id列用于其预期目的,即有效识别行而不是处理其他数据要求的方法,如果这样做,则没有必要用于AUTOINCREMENT(有开销

简言

它是否保证id将自动递增

没有

已删除行的值不会被重用?

NO对于给定的代码

适用于: -

CREATE TABLE names (id INTEGER PRIMARY KEY AUTOINCREMENT name TEXT NOT NULL)

再次NO,如果达到9223372036854775807那么将导致SQLITE_FULL错误,否则为YES

因此,当插入9223372036854775807第一行时,真正的AUTOINCREMENT才真正相关(如果id按预期/预期使用)。

也许考虑以下几点: -

DROP TABLE IF EXISTS table1;
DROP TABLE IF EXISTS table2;

CREATE TABLE IF NOT EXISTS table1 (id INTEGER PRIMARY KEY, somecolumn TEXT);
CREATE TABLE IF NOT EXISTS table2 (id INTEGER PRIMARY KEY AUTOINCREMENT, somecolumn TEXT);

INSERT INTO table1 VALUES (9223372036854775807,'blah'); 
INSERT INTO table2 VALUES (9223372036854775807,'blah');
INSERT INTO table1 (somecolumn) VALUES(1),(2),(3); 
SELECT * FROM table1;
INSERT INTO table2 (somecolumn) VALUES(1),(2),(3);

这创建了两个相似的表,唯一的区别是使用AUTOINCREMENT。每个插入的行都具有id列的最高允许值。

然后尝试插入3行,其中id将由SQLite分配。

在没有AUTOINCREMENT的情况下将3行插入到表中,但在使用AUTOINCREMENT时不会插入任何行。按照 :

CREATE TABLE IF NOT EXISTS table1 (id INTEGER PRIMARY KEY, somecolumn TEXT)
> OK
> Time: 0.098s


CREATE TABLE IF NOT EXISTS table2 (id INTEGER PRIMARY KEY AUTOINCREMENT, somecolumn TEXT)
> OK
> Time: 0.098s


INSERT INTO table1 VALUES (9223372036854775807,'blah')
> Affected rows: 1
> Time: 0.094s


INSERT INTO table2 VALUES (9223372036854775807,'blah')
> Affected rows: 1
> Time: 0.09s


INSERT INTO table1 (somecolumn) VALUES(1),(2),(3)
> Affected rows: 3
> Time: 0.087s


SELECT * FROM table1
> OK
> Time: 0s


INSERT INTO table2 (somecolumn) VALUES(1),(2),(3)
> database or disk is full
> Time: 0s

table1的SELECT结果(由于随机性可能不同)是: -

所属标签

可能回答问题的人

  • 人生的旅途

    10 粉丝484 提问5 回答
  • 无聊至极

    4 粉丝504 提问5 回答
  • 嗨喽你好

    7 粉丝480 提问4 回答
  • 富有想象力的人

    4 粉丝0 提问3 回答

扫码关注云+社区

领取腾讯云代金券