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

时间:2019-03-28 13:11:14

标签: sqlite

请考虑以下表格定义:

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

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

我在Sqlite3的文档中进行了查找,但找不到答案。

1 个答案:

答案 0 :(得分:0)

id INTEGER PRIMARY KEY自己保证(要求)一个唯一的整数值,如果没有专门指定值,则将提供一个,直到最大值达到64位带符号整数的最大允许值(9223372036854775807)之后可能会发现并应用未使用的值。

如果使用AUTOINCREMENT,则可以保证(如果未规避的话)始终提供更高的BUT值(如果达到了9223372036854775807),而不是分配未使用的数字,将导致SQLITE_FULL错误。从分配数字的角度来看,这是唯一的区别。

都不能保证单调递增的值。

没有AUTOINCREMENT的计算/算法等效于

  • 1 + max(rowid),如果该值大于9223372036854754775807,则会尝试查找未使用的值,因此会找到较低的值。

    • 我还没有看到有人遇到未分配随机未使用值的情况。

对于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(具有overheads

简而言之

  

是否保证ID会自动递增

  

已删除行的值将不会重复使用?

给定代码的

用于:-

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

,就像到达9223372036854754775807一样,将导致SQLITE_FULL错误,否则为


因此,仅当插入第9223372036854754775807的行时,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行,其中SQLite将分配 id

在没有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

表1的SELECT结果(可能由于随机性而有所不同)为:-

enter image description here