我有一个关于SQLite数据库的纯学术问题.
我正在使用SQLite.net在我的WinForm项目中使用数据库,当我设置一个新表时,我开始考虑ID列的最大值.
我使用IDENTITY
for my [ID]
列,根据SQLite.net DataType Mappings,相当于DbType.Int64
.我通常在零处启动我的ID列(将该行作为测试记录)并使数据库自动增加.
最大值(Int64.MaxValue
)为9,223,372,036,854,775,807.出于我的目的,我甚至不会在达到最大值时划伤表面,但在数据库中发生了什么呢?在尝试阅读本文时,我发现DB2显然将值"包装"到负值(-9,223,372,036,854,775,807)并从那里递增,直到数据库无法插入行,因为ID列必须是唯一的.
这是在SQLite和/或其他数据库引擎中发生的事情吗?
我怀疑是否有人确切知道,因为如果每秒插入一百万行,则需要大约292,471年才能达到环绕风险点 - 数据库已经存在了很长一段时间(实际上, Homo Sapiens也是如此;-).
IDENTITY实际上不是在SQLite中自动增加的正确方法.这将要求您在应用层中进行递增.在SQLite shell中,尝试:
create table bar (id IDENTITY, name VARCHAR); insert into bar (name) values ("John"); select * from bar;
你会看到id只是null.SQLite对IDENTITY没有任何特殊意义,因此它基本上是一个普通的(无类型)列.
另一方面,如果你这样做:
create table baz (id INTEGER PRIMARY KEY, name VARCHAR); insert into baz (name) values ("John"); select * from baz;
它会是1,因为我认为你期望.
请注意,还有一个INTEGER PRIMARY KEY AUTOINCREMENT.基本的区别在于AUTOINCREMENT确保密钥永远不会被重用.因此,如果你删除John,1永远不会被重用为id.无论哪种方式,如果你使用PRIMARY KEY(带有可选的AUTOINCREMENT)并且用完了id,SQLite应该会失败并使用SQLITE_FULL,而不是环绕.
通过使用IDENTITY,您可以打开(如果db已满)您的应用程序错误地回绕的可能性(可能无关紧要).这很有可能,因为SQLite中的IDENTITY列可以保存任何值(包括负的int).再次尝试:
insert into bar VALUES ("What the hell", "Bill"); insert into bar VALUES (-9, "Mary");
这两个都是完全有效的.它们也适用于巴兹. 但是,使用baz可以避免手动指定id.这样,你的id列永远不会有垃圾.