sqlite中有自动增量功能吗?


109

我试图primary keySqlite3中创建一个具有自动增量的。我不确定这是否真的可能,但是我希望仅指定其他领域。

例如:

CREATE TABLE people (id integer primary key auto increment, first_name varchar(20), last_name varchar(20));

然后,当我添加一个值时,我希望只需要这样做:

INSERT INTO people
VALUES ("John", "Smith");

这有可能吗?

我在Windows 7 sqlite3下运行cygwin

Answers:


167

您可以免费获得一个名为ROWID的软件。无论您是否要求,这都在每个SQLite表中。

如果包含INTEGER PRIMARY KEY类型的列,则该列指向自动ROWID列(是其别名)。

就像您期望的那样,每当插入一行时,便会为ROWID(无论您用什么名字称呼)分配一个值。如果您在INSERT上显式分配了一个非NULL值,它将获得该指定值,而不是自动递增。如果在INSERT上显式分配了NULL值,它将获得下一个自动增量值。

另外,您应尽量避免:

 INSERT INTO people VALUES ("John", "Smith");

和使用

 INSERT INTO people (first_name, last_name) VALUES ("John", "Smith");

代替。第一个版本非常脆弱-如果您曾经在表定义中添加,移动或删除列,则INSERT将会失败或产生不正确的数据(值在错误的列中)。


53
ROWID与真正的自动增量不太相同,因为SAME值可能会生成多次。例如,对于一个空表,插入3行将使第3行的ROWID如预期的那样为3。但是插入2行,删除最后一行,然后插入另一行,使插入的第三行的ROWID为2,就像第二行一样。因此,如果表引用表中发生删除的ROWID,并且在相关表中也没有进行删除或ROWID无效的表,则存在一个明显的严重问题。
尼克

10
如果从答案中看不出来,则可以在选择语句中使用ROWID,例如select rowid from people;
Colin D

@Nick只是为了补充您的想法:因此,自动递增是一种安全措施。而且,我们并不是在谈论两行在ROWID中发生冲突。
YoussefDir

68

是的,这是可能的。根据SQLite常见问题解答

声明的列INTEGER PRIMARY KEY将自动递增。


12
如Uku所述,并在文档中也作了解释,警告是您需要传递NULL来获取ID,以使其正常工作。
马特·霍尔斯

22
如果您将列列表留给INSERT,则只需要使用NULL-从来就不是一个好习惯。如果指定列,则只需省略自动增量列,它将接收下一个值。
拉里·卢斯蒂格

5
另一个警告:完全按照上面的说明写“ INTEGER ...”。快捷方式“ INT ...”将不起作用。
Marcin Wojnarski

26

截至今天-2018年6月


这是官方SQLite文档必须对此主题说的(粗体和斜体是我的):

  1. AUTOINCREMENT关键字强加额外的CPU,内存,磁盘空间和磁盘I / O开销,如果不严格需要应该避免。通常不需要。

  2. 在SQLite中,类型为INTEGER PRIMARY KEY 的列ROWID 的别名(在WITHOUT ROWID表中除外),该别名始终是64位有符号整数。

  3. 在INSERT上,如果未 显式给 ROWID或INTEGER PRIMARY KEY列赋值,则将自动用未使用的整数 填充该整数,通常比当前使用的最大ROWID多一无论是否使用AUTOINCREMENT关键字,都是如此。

  4. 如果在INTEGER PRIMARY KEY之后出现AUTOINCREMENT关键字,则会更改自动ROWID分配算法,以防止在数据库的生存期内重用ROWID。换句话说,AUTOINCREMENT的目的是防止重复使用先前删除的行中的ROWID。


11

你读过这个吗?如何创建AUTOINCREMENT字段。

INSERT INTO people
VALUES (NULL, "John", "Smith");

因此,您要说的是我试图做的事是不可能的,但我可以进行模拟。我需要在插入内容中使用null吗?
ewok 2011年

1
您无需执行任何操作,而总是插入NULL作为id,它仅说明sqlite在内部如何执行此操作。
Uku Loskit,2011年

7
当您未指定要插入的列的列表时,需要INSERT上的NULL (在这种情况下,您需要多个与列数完全匹配的值,并且必须使用NULL作为占位符)。但是,在不指定列列表的情况下进行INSERT从来都不是好习惯。如果指定列的列表,则只需省略autoincrement列和NULL值,就可以得到期望的结果。
拉里·卢斯蒂格

4

一个不应该AUTOINCREMENT在附近指定关键字PRIMARY KEY。创建自动增量主键并插入的示例:

$ sqlite3 ex1

CREATE TABLE IF NOT EXISTS room(room_id INTEGER PRIMARY KEY, name VARCHAR(25) NOT NULL, home_id VARCHAR(25) NOT NULL);

INSERT INTO room(name, home_id) VALUES ('test', 'home id test');

INSERT INTO room(name, home_id) VALUES ('test 2', 'home id test 2');

SELECT * FROM room;

会给:

1|test|home id test
2|test 2|home id test 2

4

除了rowid之外,您可以定义自己的自动递增字段,但不建议这样做。当我们使用自动增加的rowid时,这始终是更好的解决方案。

AUTOINCREMENT关键字强加了额外的CPU,内存,磁盘空间和磁盘I / O开销,如果没有严格要求,则应避免使用该关键字。通常不需要。

阅读此处以获取详细信息。


显然rowid并不总是自动增加的,请参阅Nick的评论
rogerdpack '16

1
不对。自动增量在某些方面会更好,因为它不会重用ID-这对许多系统来说都是非常重要的要求。
O'Rooney

3

SQLite AUTOINCREMENT是用于自动递增表中字段值的关键字。创建具有特定列名的表时,可以使用AUTOINCREMENT关键字自动增加字段值,以自动增加它。

关键字AUTOINCREMENT只能与INTEGER字段一起使用。句法:

AUTOINCREMENT关键字的基本用法如下:

CREATE TABLE table_name(
   column1 INTEGER AUTOINCREMENT,
   column2 datatype,
   column3 datatype,
   .....
   columnN datatype,
);

有关示例,请参见下文:考虑如下创建的COMPANY表:

sqlite> CREATE TABLE TB_COMPANY_INFO(
   ID INTEGER PRIMARY KEY   AUTOINCREMENT,
   NAME           TEXT      NOT NULL,
   AGE            INT       NOT NULL,
   ADDRESS        CHAR(50),
   SALARY         REAL
);

现在,将以下记录插入表TB_COMPANY_INFO中:

INSERT INTO TB_COMPANY_INFO (NAME,AGE,ADDRESS,SALARY)
VALUES ( 'MANOJ KUMAR', 40, 'Meerut,UP,INDIA', 200000.00 );

现在选择记录

SELECT *FROM TB_COMPANY_INFO
ID      NAME            AGE     ADDRESS             SALARY
1       Manoj Kumar     40      Meerut,UP,INDIA     200000.00

2

我知道这个答案有点晚了。
我回答这个问题的目的是,无论现在或将来使用SQLite遇到此类挑战并且遇到困难时,每个人都可以参考。

现在,回顾您的查询,应该是这样的。

CREATE TABLE people (id integer primary key autoincrement, first_name varchar(20), last_name varchar(20));

它对我有效。像这样

在此处输入图片说明

万一您使用SQLite,建议您查看DB Browser for SQLite。也可以在不同平台上使用。


0

您所做的是正确的,但是“自动增量”的正确语法应该没有空格:

CREATE TABLE people (id integer primary key autoincrement, first_name string, last_name string);

(还请注意,我将您的varchars更改为字符串。这是因为SQLite在内部将varchar转换为字符串,所以为什么要打扰?)

那么您的插入内容应尽可能采用SQL语言:

INSERT INTO people(id, first_name, last_name) VALUES (null, 'john', 'doe');

的确,如果省略id,它会自动递增和分配,但我个人不希望将来会更改自动机制。

关于自动增量的说明:尽管,正如许多人指出的那样,SQLite人员不建议这样做,但如果不使用自动增量,我不喜欢自动重用已删除记录的ID。换句话说,我喜欢已删除记录的ID永远不会再出现。

高温超导


在这方面,我完全同意奥鲁尼所说的。
卡·纳内蒂
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.