SQLite PRIMARY 键自动增量不起作用

Posted

技术标签:

【中文标题】SQLite PRIMARY 键自动增量不起作用【英文标题】:SQLite PRIMARY key AutoIncrement doesn't work 【发布时间】:2015-08-06 00:23:16 【问题描述】:

我正在尝试创建一个带有自动递增主键的表。包括用于创建表的 SQL 查询。 问题是自动增量不起作用。这意味着当我插入一行以 NULL 作为conversation_id 的值时,它只会插入null。我在多个表上都有这个问题。

-- Table: conversations
CREATE TABLE conversations (
    conversation_id INTEGER (64) PRIMARY KEY
                                 UNIQUE,
    target_id       BIGINT (64),
    sender_id       BIGINT (64),
    status          STRING (16)  NOT NULL
                                 DEFAULT unseen,
    is_group        INTEGER (1)  NOT NULL
                                 DEFAULT (0),
    last_update     INTEGER (32) DEFAULT (0),
    target_name     STRING (64),
    target_photo    STRING (256),
    unread_count    INTEGER (10) DEFAULT (0),
    last_message    STRING (256) 
);

以下是我用来插入表格的方法:

public Conversation addConversation(Conversation conversation) 
        SQLiteDatabase db = getWritableDatabase();
        ContentValues row = new ContentValues();

        row.put("target_id", conversation.getTargetID());
        row.put("sender_id", conversation.getSenderID());
        row.put("target_name", conversation.getTargetName());
        row.put("target_photo", conversation.getTargetPhoto());
        row.put("status", conversation.getStatus());
        row.put("unread_count", conversation.getUnreadCount());
        row.put("last_message", conversation.getLastMessage());

        conversation.setConversationID(db.insert(TBL_CONVERSATIONS, null, row));
        Log.d(TAG, "conversation added: "+conversation.getConversationID());

        db.close();

        return conversation;
    

这里奇怪的是,当我从 insert 方法中检索插入 id 时,它返回正确的值,但实际的数据库字段为空。

如果我理解正确A column declared INTEGER PRIMARY KEY will autoincrement.[Cite]

【问题讨论】:

以下划线开头,例如:_id。 @Krupal 没有成功我的朋友。 【参考方案1】:

我只是在查询中添加了自动增量,它工作正常。

喜欢这个

id  integer primary key autoincrement

【讨论】:

【参考方案2】:

来自文档:

使用 CREATE TABLE AS 创建的表没有 PRIMARY KEY 并且没有 任何形式的约束。每列的默认值为NULL。

您不必在具有 PRIMARY KEY 约束的 COLUMN 上添加 UNIQUE 约束。 说明:

UNIQUE 约束类似于 PRIMARY KEY 约束,除了 单个表可能有任意数量的 UNIQUE 约束。

改为添加NOT NULL。 这就是为什么:

根据 SQL 标准,PRIMARY KEY 应该总是暗示 NOT 空值。不幸的是,由于一些早期版本中的错误,这不是 SQLite 中的案例。除非该列是 INTEGER PRIMARY KEY 或 表是 WITHOUT ROWID 表或列被声明为 NOT NULL, SQLite 允许在 PRIMARY KEY 列中使用 NULL 值。 SQLite 可能是 固定以符合标准,但这样做可能会破坏传统 应用程序。因此,决定仅记录事实 该 SQLite 允许在大多数 PRIMARY KEY 列中使用 NULL。

我建议使用此列定义:

CREATE TABLE conversations (
    conversation_id INTEGER PRIMARY KEY NOT NULL AUTOINCREMENT,
...

【讨论】:

我已经测试了 NOT NULL,但由于这个约束,它无法完全插入一行。 终于!似乎应该明确声明AUTOINCEREMENT【参考方案3】:

您看到的返回值很可能是该行的ROWIDROWID 是每个表中可用的隐藏列,除非明确删除。根据官方文档,当您定义INTEGER PRIMARY KEY 时,它应该自动成为ROWID 的别名。这也是当您以这种方式定义列时不需要AUTOINCREMENT 的原因。

除了下面提到的一个例外,如果一个 rowid 表有一个主键 由单个列和该列的声明类型组成 在大小写的任何混合中为“INTEGER”,则该列 成为 rowid 的别名。这样的列通常被称为 作为“整数主键”。 PRIMARY KEY 列仅成为 如果声明的类型名称恰好是“INTEGER”,则为整数主键。 其他整数类型名称,如“INT”或“BIGINT”或“SHORT INTEGER”或 “UNSIGNED INTEGER”使主键列表现为 具有整数亲和性和唯一索引的普通表列,而不是 rowid 的别名。

见:CREATE TABLE documentation

您的列不是INTEGER,或者不是PRIMARY KEY。仔细查看您的创建语句,我可以看到一两个可能的罪魁祸首。

唯一与主键

默认情况下,主键是唯一的。根据语法定义(您可以在与上述引用相同的文档页面上找到),您应该选择PRIMARY KEYUNIQUE,而不是两者。

列长度限制

ROWID 默认已经是 64 位了。您已指定长度 64,但未以位为单位指定长度。您可能在这里指定了一个 64 字节的整数,我确定这不是故意的。然而,这实际上应该不是问题,因为SQLite ignores length-constraints。所以指定它们没有意义。

TLDR

替换此代码:

conversation_id INTEGER (64) PRIMARY KEY UNIQUE

有了这个:

conversation_id INTEGER PRIMARY KEY AUTOINCREMENT

【讨论】:

以上是关于SQLite PRIMARY 键自动增量不起作用的主要内容,如果未能解决你的问题,请参考以下文章

CentOS 6 - YUM 不起作用 - primary.sqlite.bz2 [错误 -1] 元数据文件与校验和不匹配

用整数替换 sqlite.net “bigint” 以实现自动增量主键约束

是否可以为使用 python 的 sqlite3 中的主键自动增量列选择第一个值?

MongoDB自动增量不起作用

MongoDB自动增量不起作用

GORM 和 SQL Server:自动增量不起作用