首页 > 解决方案 > SQLite 自动增量未插入

问题描述

我有一个 SQLite 数据库,当我插入 ID 时,应该使用 AUTOINCREMENT 自动递增。

但它始终为空。

这是创建表

    @Override
       public void onCreate(SQLiteDatabase db) {
       db.execSQL("CREATE TABLE ausgaben (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, TAG text,DATUM text, AUSGABE text, MENGE text, KATEGORIE text)");
    }

这就是我插入数据的方式:

    public boolean insertAusgabe(String tag, String datum, String ausgabe, String menge, String kategorie){
    SQLiteDatabase db = this.getWritableDatabase();
    ContentValues contentValues = new ContentValues();
    contentValues.putNull("id");
    contentValues.put(AUSGABEN_TAG,tag);
    contentValues.put(AUSGABEN_DATUM,datum);
    contentValues.put(AUSGABEN_AUSGABE,ausgabe);
    contentValues.put(AUSGABEN_MENGE,menge);
    contentValues.put(AUSGABEN_KATEGORIE,kategorie);
    db.insert(TABLE_NAME,null,contentValues);
    return true;
}

如果我理解正确,这应该可以正常工作。但是数据库看起来像这样: 在此处输入图像描述

标签: androidandroid-sqlitesqliteopenhelper

解决方案


您似乎希望 id 列为空而不是数字。

如果您编写代码id INTEGER PRIMARY KEY NOT NULL AUTOINCREMENT请参阅下面有关 AUTOINCREMENT 的注释),那么该列是一个特殊列,它是rowid列的别名(除非该表已使用 WITHOUT ROWID 定义)。

rowid列不能为空,并且必须是整数值。如果尝试插入列的值为空(或未指定)的行,则 SQLite 将分配一个整数值(对于 java 为 long)。1 如果表中没有行,则 1 大于使用的最大数。

因此,为什么您在 id 列中有一系列数字。

例如,如果表是使用id INT PRIMARY KEY NOT NULLthen 定义的,则id列不是rowid列的别名。(然后不能使用 AUTOINCREMENT,因为它只能用于rowid列的别名)然后没有任何插入将起作用,因为 id 列的值将为 NULL,由于 NOT NULL 约束的编码将导致在约束冲突中。

但是,如果使用 定义列,则允许idid INT PRIMARY KEY为空值。请注意,编码 PRIMARY KEY 意味着一个 UNIQUE 约束,即所有值都必须是唯一的。SQLite 认为所有 NULL 值彼此比较是唯一的。

因此,最后一个定义将允许看起来是您预期的结果。然而,一个不确定的值对于标识一行有什么用呢?(这是修辞)。

因此,您最初获得的结果是更有用的结果。即使不是故意的。


关于自动增量的说明

AUTOINCREMENT很可能不需要,这指定了rowid确定算法的扩展,因为它

  • 强制最新的rowid值大于任何现有的或使用的rowid

也就是说,它依赖于另一个表,即sqlite_sequence来记录分配的最高rowid,然后它使用最高的现有rowid或为 sqlite_sequence 表中的表存储的值中的较高者。

当已分配最高可能值 (9223372036854775807) 并尝试插入新行时,使用AUTOINCREMENT 。然后将导致 SQLITE_FULL 错误。如果没有,则尝试使用随机未使用的值(例如,如果行已被删除)。

使用AUTOINCREMENT会有开销(根据What are the overheads of using AUTOINCREMENT for SQLite on Android? 大约为8-12% )。

笔记

需要注意的是,不保证rowid,不管有没有AUTOINCREMENT关键字都会增加1。在某些情况下,值可能会被跳过

请注意,“单调递增”并不意味着 ROWID 总是恰好递增 1。一种是通常的增量。但是,如果插入由于(例如)唯一性约束而失败,则失败插入尝试的 ROWID 可能不会在后续插入中重用,从而导致 ROWID 序列中的间隙。AUTOINCREMENT 保证自动选择的 ROWID 会增加,但不保证它们是连续的。

SQLite 自动增量

*简而言之,将 *列期望为除了有效识别行的方法之外的任何东西都是不明智的。id/rowid


推荐阅读