【问题标题】:Is there an auto increment in sqlite?sqlite中是否有自动增量?
【发布时间】:2011-12-15 21:24:49
【问题描述】:

我正在尝试在Sqlite3 中创建一个具有自动递增primary key 的表。我不确定这是否真的可行,但我希望只需要指定其他字段。

例如:

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 中的 cygwin 下运行 sqlite3

【问题讨论】:

    标签: sql sqlite cygwin


    【解决方案1】:

    您可以免费获得一个,称为 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 将失败或产生不正确的数据(值在错误的列中)。

    【讨论】:

    • ROWID 与真正的自动增量并不完全相同,因为 SAME 值可能会多次生成。例如,对于一个空表,插入 3 行后,第三行的 ROWID 为 3,正如预期的那样。但是插入 2 行,删除最后一行并插入另一行,给插入的第 3 行的 ROWID 为 2,就像第 2 行一样。因此,如果表引用发生删除的表中的 ROWID 并且在相关表中也没有执行删除或 ROWID 置空,则会出现明显的严重问题。
    • 如果答案不明显,您可以在选择语句中使用 ROWID,例如select rowid from people;
    • @Nick 只是为了补充您的想法:所以自动增量是一种安全措施。而且我们不是在谈论 ROWID 中的两行冲突。
    【解决方案2】:

    是的,这是可能的。根据SQLite FAQ

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

    【讨论】:

    • 需要注意的是,正如 Uku 所提到的,并且在文档中也有解释,您需要为 ID 传递一个 NULL 才能使其正常工作。
    • 如果您将列列表留给 INSERT,您只需 需要 使用 NULL — 这绝不是一个好习惯。如果您指定列,您可以简单地省略自动增量列,它将接收下一个值。
    • 另一个警告:完全按照上面给出的写“INTEGER ...”。速记“INT ...”将不起作用。
    • @MarcinWojnarski 这是我所缺少的,我认为 INT 可以工作,但问题是改用 INTEGER,否则数据的 ID 列值为 None
    【解决方案3】:

    截至今天 - 2018 年 6 月


    以下是official SQLite documentation 对此主题的看法(粗体和斜体是我的):

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

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

    3. 在 INSERT 上,如果 ROWID 或 INTEGER PRIMARY KEY 列不是 明确给出一个值,然后它会自动填充一个 未使用的整数,通常比当前最大的 ROWID 大一 使用。 无论是否使用 AUTOINCREMENT,这都是正确的 使用关键字。

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

    【讨论】:

      【解决方案4】:

      你读过这个吗? How do I create an AUTOINCREMENT field.

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

      【讨论】:

      • 所以你说的是我想要做的事情是不可能的,但我可以模拟。我需要在插入中使用 null 吗?
      • 你不需要做任何事情,但总是插入 NULL 作为 id,它只是解释了 sqlite 是如何在内部进行的。
      • 如果您没有指定要插入的列列表,则需要 INSERT 上的 NULL(在这种情况下,您需要一些与列,并且必须使用 NULL 作为占位符)。但是在不指定列列表的情况下执行 INSERT 绝不是好的做法。如果您指定列的列表,只需同时省略自动增量列和 NULL 值,您就会得到您期望的结果。
      【解决方案5】:

      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
      

      【讨论】:

        【解决方案6】:

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

        $ 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
        

        【讨论】:

          【解决方案7】:

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

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

          阅读here了解详细信息。

          【讨论】:

          • 显然 rowid 并不总是自动增加,请参阅 Nick 的评论
          • 不正确。自动增量在某些方面更好,因为它不会重复使用 ID——对于许多系统来说这是一个非常重要的要求。
          【解决方案8】:

          我知道这个答案有点晚了。
          我这个答案的目的是供大家参考,如果他们现在或将来遇到这种类型的 SQLite 挑战并且他们遇到困难。

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

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

          它对我有用。像这样,

          以防万一您正在使用 SQLite,我建议您查看 DB Browser for SQLite。也适用于不同的平台。

          【讨论】:

            【解决方案9】:

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

            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 永远不会再出现。

            HTH

            【讨论】:

            • 在这方面我完全赞同奥鲁尼所说的话。
            • 如果您尝试在数据库浏览器中检查 SQLite 的修改表对话框中的 AI 框,如果表中已经有记录,它将不会保存。我的解决方法是导出“所有内容”并修改 .sql 文件的 PK 规范以添加 AUTOINCREMENT,然后使用该文件导入回数据库。它不仅保留了 AI,而且保留了 PK 值,即使它们不是从 1 开始。
            猜你喜欢
            • 2013-09-21
            • 1970-01-01
            • 2017-01-16
            • 2017-03-07
            • 1970-01-01
            • 2015-06-08
            • 1970-01-01
            • 1970-01-01
            • 2011-11-13
            相关资源
            最近更新 更多