SQLite Android:插入数据失败“NOT NULL约束失败:最后一条记录的call_table.ID”

时间:2018-01-12 01:36:20

标签: android sqlite

我正在尝试在SQLite表中存储联系信息,但

这就是我创建表格的方式:

 private static final String SQL_CREATE_QUERY = "create table " + CONTACT_TABLE +
            "( ID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL , " +
            NUMBER_COLUMN + " TEXT , " +
            CALL_TIME_COLUMN + " TEXT , " +
            CALLER_NAME_COLUMN + " TEXT , " +
            " ) ";

但是当我尝试存储178条记录时,它在最后一条记录中失败

    ContentValues contentValues = new ContentValues();
    contentValues.put(NUMBER_COLUMN, callerInforToInsert.getCallerNumber());
    contentValues.put(CALL_TIME_COLUMN, callerInforToInsert.getCallTime());
    contentValues.put(CALLER_NAME_COLUMN, callerInforToInsert.getCallerName());
    long result = writableDatabase.insert(CONTACT_TABLE , null, contentValues);
    writableDatabase.close();
    Log.w(TAG, "Inserted " + result);

它抛出ID为null的约束异常。但是我自动递增ID我没有手动分配。

                                                              android.database.sqlite.SQLiteConstraintException: NOT NULL constraint failed: call_table.ID (code 1299)
                                                                  at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
                                                                  at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:782)
                                                                  at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
                                                                  at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
                                                                  at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1472)
                                                                  at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1343)
                                                                  at com.rasfi.ai.domain.engine.DataBaseHelper.insertRow(DataBaseHelper.java:94)
                                                                  at com.rasfi.ai.domain.engine.DataBaseHelper.insertList(DataBaseHelper.java:114)
                                                                  at com.rasfi.ai.ui.fragment.CallsRecordingsFragment$WorkLoadHandler.doInBackground(CallsRecordingsFragment.java:126)
                                                                  at com.rasfi.ai.ui.fragment.CallsRecordingsFragment$WorkLoadHandler.doInBackground(CallsRecordingsFragment.java:105)
                                                                  at android.os.AsyncTask$2.call(AsyncTask.java:304)
                                                                  at java.util.concurrent.FutureTask.run(FutureTask.java:237)
                                                                  at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
                                                                  at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
                                                                  at java.lang.Thread.run(Thread.java:760)

任何提示都表示赞赏。

2 个答案:

答案 0 :(得分:1)

您的问题很可能是由于表创建的SQL不正确。在最后一列之后,您有一个阴谋逗号 ,

而不是: -

    private static final String SQL_CREATE_QUERY = "create table " + CONTACT_TABLE +
        "( ID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL , " +
        NUMBER_COLUMN + " TEXT , " +
        CALL_TIME_COLUMN + " TEXT , " +
        CALLER_NAME_COLUMN + " TEXT , " + //<<<<< , = ouch
        " ) ";

尝试: -

    private static final String SQL_CREATE_QUERY = "create table " + CONTACT_TABLE +
        "( ID INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL , " +
        NUMBER_COLUMN + " TEXT , " +
        CALL_TIME_COLUMN + " TEXT , " +
        CALLER_NAME_COLUMN + " TEXT " +
        " ) ";

显然,您需要确保删除并创建表。删除App的数据或卸载App可能最简单。除非您有需要保留的数据,否则您必须确定如何保留数据(ALTER可能重命名该表)。

根据评论NOT NULL是多余的,AUTOINCREMENT也很有可能是超级符号: -

  

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

使用INTEGER PRIMARY KEY将为您提供一般增加的唯一ID(不保证当您点击9223372036854775807时,它将使用未使用的数字,因为当达到9223372036854775807时AUTOINCREMENT保证更高的数字它将发出SQLITE_FULL异常而不是使用未使用的数字。)

使用AUTOINCREMENT时产生的额外资源以SQLIte为中心创建一个附加表,即 sqlite_seqeunce ,其中它基于每个表存储最后生成的rowid(id) (2列名称(表名)和 seq (序列号)。

答案 1 :(得分:1)

如果您使用的是Room API

@PrimaryKey(autoGenerate = true)
@NonNull
@ColumnInfo(name = ID_COLUMN)
private int id;