唯一约束失败:sqlite 数据库:android

Posted

技术标签:

【中文标题】唯一约束失败:sqlite 数据库:android【英文标题】:UNIQUE constraint failed: sqlite database : android 【发布时间】:2016-05-01 00:38:27 【问题描述】:

我正在尝试在表中插入值。但是只插入了一个值。当我尝试插入新值时,在 log cat 中出现错误。

日志猫显示:

abort at 13 in [INSERT INTO event(totalminutesfrom,dayofweek,title,location,totalminutesto,id) VALUES (?,?,?,?,?,?)]: UNIQUE constraint failed: event.id
01-24 11:34:39.764 7763-7763/com.example.siddhi.timetablelayout E/SQLiteDatabase: Error inserting totalminutesfrom=694 dayofweek=null title=qxs location=Eded & Mariz totalminutesto=0 id=0
01-24 11:34:39.764 7763-7763/com.example.siddhi.timetablelayout E/SQLiteDatabase: android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: event.id (code 1555)
01-24 11:34:39.764 7763-7763/com.example.siddhi.timetablelayout E/SQLiteDatabase:     at android.database.sqlite.SQLiteConnection.nativeExecuteForLastInsertedRowId(Native Method)
01-24 11:34:39.764 7763-7763/com.example.siddhi.timetablelayout E/SQLiteDatabase:     at android.database.sqlite.SQLiteConnection.executeForLastInsertedRowId(SQLiteConnection.java:782)
01-24 11:34:39.764 7763-7763/com.example.siddhi.timetablelayout E/SQLiteDatabase:     at android.database.sqlite.SQLiteSession.executeForLastInsertedRowId(SQLiteSession.java:788)
01-24 11:34:39.764 7763-7763/com.example.siddhi.timetablelayout E/SQLiteDatabase:     at android.database.sqlite.SQLiteStatement.executeInsert(SQLiteStatement.java:86)
01-24 11:34:39.764 7763-7763/com.example.siddhi.timetablelayout E/SQLiteDatabase:     at android.database.sqlite.SQLiteDatabase.insertWithOnConflict(SQLiteDatabase.java:1471)
01-24 11:34:39.764 7763-7763/com.example.siddhi.timetablelayout E/SQLiteDatabase:     at android.database.sqlite.SQLiteDatabase.insert(SQLiteDatabase.java:1341)
01-24 11:34:39.764 7763-7763/com.example.siddhi.timetablelayout E/SQLiteDatabase:     at com.example.siddhi.timetablelayout.EventTableHelper.addEvent(EventTableHelper.java:76)
01-24 11:34:39.764 7763-7763/com.example.siddhi.timetablelayout E/SQLiteDatabase:     at com.example.siddhi.timetablelayout.AddEventActivity$5.onClick(AddEventActivity.java:217)

插入行时这两行显示错误。

db.insert(TABLE, null, values);

   db.addEvent(new EventData(eventTitle,dayOfWeek,totalMinutesFrom, totalMinutesTo,location));

EventTableHelper

public class EventTableHelper extends SQLiteOpenHelper 


    private static final String TABLE = "event";
    private static final String KEY_ID = "id";
    private static final String KEY_TITLE = "title";
    private static final String KEY_LOCATION = "location";
    private static final String KEY_DAY_OF_WEEK = "dayofweek";
    private static final String KEY_TOTAL_MINUTES_FROM = "totalminutesfrom";
    private static final String KEY_TOTAL_MINUTES_TO = "totalminutesto";



    public EventTableHelper(Context context) 
        super(context, Constants.DATABASE_NAME, null, Constants.DATABASE_VERSION);
        //3rd argument to be passed is CursorFactory instance
    

    // Creating Tables
    @Override
    public void onCreate(SQLiteDatabase db) 
        //createTable(db);
    

    public void createTable(SQLiteDatabase db)
        String CREATE_EVENTS_TABLE = "CREATE TABLE " + TABLE + "("
                + KEY_ID + " INTEGER PRIMARY KEY," + KEY_TITLE + " TEXT,"
                + KEY_DAY_OF_WEEK +"TEXT" + KEY_TOTAL_MINUTES_FROM +"INTEGER"
                + KEY_TOTAL_MINUTES_TO + "INTEGER" +  KEY_LOCATION + "TEXT" +  ")";

        db.execSQL(CREATE_EVENTS_TABLE);

    
    // Upgrading database
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 
        // Drop older table if existed
       // db.execSQL("DROP TABLE IF EXISTS " + TABLE);

      //  createTable(db);

        // Create tables again
        //onCreate(db);
    

    // code to add the new contact
    public void addEvent(EventData event) 
        SQLiteDatabase db = this.getWritableDatabase();

        ContentValues values = new ContentValues();
        values.put(KEY_ID, event.getId());
        values.put(KEY_TITLE,event.getTitle()); // Contact Name
        values.put(KEY_DAY_OF_WEEK,event.getDayofWeek());
        values.put(KEY_TOTAL_MINUTES_FROM,event.getFromMinutes());
        values.put(KEY_TOTAL_MINUTES_TO,event.getToMinutes());
        values.put(KEY_LOCATION,event.getLocation());
        // Inserting Row
        db.insert(TABLE, null, values);
        //2nd argument is String containing nullColumnHack
        db.close(); // Closing database connection
    

    // code to get the single contact
   EventData getEvent(int id) 
        SQLiteDatabase db = this.getReadableDatabase();

        Cursor cursor = db.query(TABLE, new String[]  KEY_ID,
                        KEY_TITLE, KEY_DAY_OF_WEEK, KEY_TOTAL_MINUTES_FROM,KEY_TOTAL_MINUTES_TO,KEY_LOCATION , KEY_ID + "=?",
                new String[]  String.valueOf(id) , null, null, null, null);
        if (cursor != null)
            cursor.moveToFirst();
       EventData eventData = new EventData(Integer.parseInt(cursor.getString(0)),cursor.getString(1), cursor.getString(2),
               cursor.getInt(3),cursor.getInt(4),cursor.getString(5));

        return eventData;
    



    // code to get all contacts in a list view
    public List<EventData> getAllEvents() 
        List<EventData> conList = new ArrayList<EventData>();
        // Select All Query
        String selectQuery = "SELECT  * FROM " + TABLE;

        SQLiteDatabase db = this.getWritableDatabase();
        Cursor cursor = db.rawQuery(selectQuery, null);

        // looping through all rows and adding to list
        if (cursor.moveToFirst()) 
            do 

                EventData event = new EventData();

                event.setId(Integer.parseInt(cursor.getString(0)));
                event.setTitle(cursor.getString(1));
                event.setDayofWeek(cursor.getString(2));
                event.setFromMinutes(cursor.getInt(3));
                event.setToMinutes(cursor.getInt(4));
                event.setLocation(cursor.getString(5));
                // Adding contact to list
                conList.add(event);
             while (cursor.moveToNext());
        

        // return contact list
        return conList;
    

如何解决这个问题??

【问题讨论】:

您正在尝试插入一个已经存在的 ID。由于密钥是唯一的,因此您不能。 我应该编辑什么代码? @Hrundi V. Bakshi 我会将键设为自动增量键。然后我不会传递 ID,因为它会自动生成。 ***.com/a/45299979/6665568 。这个答案完全为我解决了这个问题。如果您直接想要替换行已经存在,则处理案例。 【参考方案1】:

适用于使用Room Persistence Library 的开发人员。你可以使用

@Insert(onConflict = OnConflictStrategy.REPLACE)  // or OnConflictStrategy.IGNORE

在DAO中根据Insert Documentation

【讨论】:

但它只是要替换现有行...如果您真的想更新项目,那么您应该使用@Update@Insert 用于添加新项目 谢谢。这个答案应该被接受,而不是上面一个。 请注意,如果您使用 CASCADE DELETION,它将删除此相关对象的所有相关对象【参考方案2】:

您的代码可能违反了主键对 KEY_ID 字段的唯一性约束。

两种可能的解决方案是:

    确保您的EventData.getId() 返回每​​个对象的唯一值。目前,我没有看到您将任何标识符传递给它的构造函数,并且可能所有事件都插入了相同的 id 值。 如果您不关心自己生成 id,可以将 AUTOINCREMENT 设置添加到您的 KEY_ID 列定义中。这样KEY_ID 字段将被自动填充,并且每一行都有自己的唯一值。到达那里后,不要忘记自己删除将KEY_ID 添加到ContentValues

【讨论】:

非常感谢...第二个解决方案对我有用...没有插入 id..@Mateusz Herych 哇,第一个对我有用,谢谢@Mateusz Herych 一个问题是,我们可以用 try catch 包围插入吗? 我猜不是,因为插入是由一个线程异步完成的【参考方案3】:

如果你使用 Room,那么你应该使用 @PrimaryKey 而不是 @PrimaryKey(autoGenerate = true)

并使您的 id 变量可选:

@Entity(tableName = "contact_table") data class Contact(@PrimaryKey(autoGenerate = true) @ColumnInfo(name = "id") var id: Long?, @ColumnInfo(name = "name") val name: String, @ColumnInfo(name = "phone") val phone: String)

然后在添加新项目时,将null 作为 id 传递,insert func 将返回新 id,将其添加到您的对象中

val contact = Contact(null, name, phone)
contact.id = ContactRoomDatabase.getDatabase().contactDao().insert(contact)

【讨论】:

使id非空也可以。将0 传递给id,insert func 也会返回新的id【参考方案4】:

该表具有唯一约束。这意味着给定 ID 值只能存在一行。如果您尝试更改某行的某些值,请使用 UPDATE 而不是 INSERT。如果您尝试添加此行,则需要为其提供不同的唯一 ID,或者您需要先删除预先存在的行。哪个是正确答案取决于您的应用在做什么。

【讨论】:

【参考方案5】:

尝试检查 ID 是否已存在。如果为 true,请不要插入,因为您已经拥有具有此 ID 的行。

【讨论】:

【参考方案6】:

这是数据库中记录的重复ID的情况。只需清除应用程序存储,然后重试。一个好的解决方案是在您的 Dao 类中添加以下内容。

    @Insert (onConflict = OnConflictStrategy.REPLACE)

此问题的正确解决方案是确保 id 是唯一的。请看看这个Google Codelabs Room Example

另一种避免这种情况的方法是添加 @PrimaryKey(autoGenerate = true)

【讨论】:

【参考方案7】:

我的错误是,我尝试填写 ID 列,尽管它已经定义为 INTEGER PRIMARY KEY AUTOINCREMENT

【讨论】:

【参考方案8】:

使id列id整型自增,不把id值放入内容值中。

【讨论】:

【参考方案9】:

我最初把新的唯一约束婴儿放在旧的。相反,请确保您当前的唯一列是第一个:

CREATE TABLE TEST (client_id TEXT unique, remote_id INT unique)

【讨论】:

【参考方案10】:

对于 Kotlin 模型类

如果您像这样为主键分配一个默认值

data class MyModel(
 @PrimaryKey(autoGenerate = true) val id: Int = defaultValue
)

确保LongInt 类型的默认值为0


来自autoGenerate 评论:

如果字段类型为longint(或其TypeConverter 将其转换为longint),Insert 方法将0 视为未设置 在插入项目时。

在我的例子中,我使用-1 作为默认值并且发生了这个错误。

【讨论】:

【参考方案11】:

我遇到了同样的问题,问题是我忘记在我的DbHelper 中添加db.execSQL(YOUR_TABLE);

【讨论】:

【参考方案12】:

伙计们,我遇到了同样的问题,我从 android 设置中清除了我的本地数据库并清除了运行应用程序,这对我有用。也许你在 db 中做了一点改动,然后你忘记了。

【讨论】:

以上是关于唯一约束失败:sqlite 数据库:android的主要内容,如果未能解决你的问题,请参考以下文章

数据库导入后核心数据唯一约束失败

插入 android.database.sqlite.SQLiteConstraintException 时出错:NOT NULL 约束失败:result.high(代码 1299)

如何在 SQLiteConstraintException 上捕获列名唯一约束失败

C# Sqlite '约束失败'

SQLite 错误 19:“外键约束失败”

SQLite EF Core - '外键约束失败'