代码之家  ›  专栏  ›  技术社区  ›  Magnus

有没有办法不自动递增就生成一个自动生成的主键?

  •  4
  • Magnus  · 技术社区  · 6 年前

    我的房间数据库具有以下实体:

    @Entity
    public class SmsMessage {
        @PrimaryKey
        public long id;
    
        public boolean incoming;
        public String sender;
        public String receiver;
        public String body;
        public long timestamp;
    }
    

    此操作失败,原因如下 RuntimeException

    SQLiteConstraintException: PRIMARY KEY must be unique (code 19)
    

    生成的SQL CREATE TABLE 声明如下:

    CREATE TABLE `SmsMessage` (
        `id`    INTEGER NOT NULL,
        `incoming`  INTEGER NOT NULL,
        `sender`    TEXT,
        `receiver`  TEXT,
        `body`  TEXT,
        `timestamp` INTEGER NOT NULL,
        PRIMARY KEY(`id`)
    );
    

    这似乎不同于 INTEGER NOT NULL PRIMARY KEY the SQLite documentation .

    看来我得用 @PrimaryKey (autogenerate=true) 以便腾出空间自动生成主键值。使用时查看生成的数据库 autogenerate=true ,这将生成以下SQL:

    CREATE TABLE `SmsMessage` (
        `id`    INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
        `incoming`  INTEGER NOT NULL,
        `sender`    TEXT,
        `receiver`  TEXT,
        `body`  TEXT,
        `timestamp` INTEGER NOT NULL
    );
    

    看来 自动生成=真 对应于SQLite AUTOINCREMENT . 然而, the SQLite documentation 很清楚地表明 自动递增 不需要(在大多数情况下不建议)来自动生成唯一的主键。目的 基本上是为了防止重复使用已使用但已删除的主键。

    如果不是严格需要的话应该避免

    在INSERT中,如果ROWID或INTEGER主键列没有显式给定值,那么它将自动填充一个未使用的整数,通常比当前使用的最大ROWID多一个。无论是否使用AUTOINCREMENT关键字,这都是正确的。

    如果AUTOINCREMENT关键字出现在INTEGER主键之后,则会更改自动ROWID分配算法,以防止在数据库的生存期内重用ROWID。换句话说,

    @PrimaryKey(autogenerate=true) 通常不需要也不推荐。但只使用 @PrimaryKey 单靠它根本不会自动生成值。

    我怎么告诉房间我想要的是 'id' INTEGER NOT NULL PRIMARY KEY ?

    1 回复  |  直到 4 年前
        1
  •  4
  •   ianhanniballake    6 年前

    目前这是不可能的-唯一的选择是 AUTOINCREMENT . 你可以成为明星 existing feature request 有关此用例支持的进度更新。