唯一约束失败:sqlite 数据库:android
UNIQUE constraint failed: sqlite database : android
我正在尝试在 table 中插入值。但是只插入了一个值。当我尝试插入新值时,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.onClick(AddEventActivity.java:217)
插入行时这两行显示错误。
db.insert(TABLE, null, values);
db.addEvent(new EventData(eventTitle,dayOfWeek,totalMinutesFrom, totalMinutesTo,location));
事件表助手
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;
}
}
如何解决这个问题?
table 有唯一约束。这意味着只有一行具有给定的 ID 值。如果您尝试更改某行的某些值,请使用 UPDATE 而不是 INSERT。如果您尝试添加此行,则需要为其提供不同的唯一 ID,或者您需要先删除 pre-existing 行。哪一个是正确答案取决于您的应用程序在做什么。
您的代码可能违反了主键对 KEY_ID
字段的唯一性约束。
两种可能的解决方案是:
- 确保每个对象的
EventData.getId()
returns 唯一值。现在,我没有看到您将任何标识符传递给它的构造函数,也许所有事件都使用相同的 id
值插入。
- 如果您不关心自己生成 ID,可以将
AUTOINCREMENT
设置添加到 KEY_ID
列定义中。这样 KEY_ID
字段将自动填充,每一行都有自己的唯一值。到达那里后,不要忘记自己删除将 KEY_ID
添加到 ContentValues
。
尝试检查该 ID 是否已存在。如果为 true,则不要插入,因为您已经有了具有此 ID 的行。
我原来放的是旧的new unique constraint infant。相反,请确保您当前的唯一列是第一个:
CREATE TABLE TEST (client_id TEXT unique, remote_id INT unique)
我的错误是,我试图填充 ID
列,尽管它已经被定义为 INTEGER PRIMARY KEY AUTOINCREMENT
使id列id整型自增,id值不放入content值中
对于使用 Room Persistence Library 的开发者。您可以使用
@Insert(onConflict = OnConflictStrategy.REPLACE) // or OnConflictStrategy.IGNORE
在 DAO 中
我遇到了同样的问题,问题是我忘记在 DbHelper
中添加 db.execSQL(YOUR_TABLE);
如果您使用 房间 那么您应该使用 @PrimaryKey(autoGenerate = true)
而不是 @PrimaryKey
并使您的 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将return新id,将其添加到您的对象
val contact = Contact(null, name, phone)
contact.id = ContactRoomDatabase.getDatabase().contactDao().insert(contact)
这是数据库中记录id重复的情况。只需清除应用程序存储空间,然后重试。一个好的解决方案是在您的 Dao class.
下方添加
@Insert (onConflict = OnConflictStrategy.REPLACE)
这个问题的正确解决方法是确保id是唯一的。请看看这个Google Codelabs Room Example
另一种避免这种情况的方法是添加 @PrimaryKey(autoGenerate = true)
对于 Kotlin 模型 类
如果您要像这样向主键分配 默认值:
data class MyModel(
@PrimaryKey(autoGenerate = true) val id: Int = defaultValue
)
确保 Long
和 Int
类型的默认值为 0
。
来自 autoGenerate
评论:
If the field type is long
or int
(or its TypeConverter converts it to a long
or int
), Insert
methods treat 0
as not-set while inserting the item.
在我的例子中,我使用 -1
作为默认值并且发生了这个错误。
伙计们,我遇到了同样的问题,我从 android 设置中清除了我的本地数据库并清除了 运行 应用程序,这对我有用。也许你在数据库中做了一点改变而你忘记了。
我正在尝试在 table 中插入值。但是只插入了一个值。当我尝试插入新值时,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.onClick(AddEventActivity.java:217)
插入行时这两行显示错误。
db.insert(TABLE, null, values);
db.addEvent(new EventData(eventTitle,dayOfWeek,totalMinutesFrom, totalMinutesTo,location));
事件表助手
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;
}
}
如何解决这个问题?
table 有唯一约束。这意味着只有一行具有给定的 ID 值。如果您尝试更改某行的某些值,请使用 UPDATE 而不是 INSERT。如果您尝试添加此行,则需要为其提供不同的唯一 ID,或者您需要先删除 pre-existing 行。哪一个是正确答案取决于您的应用程序在做什么。
您的代码可能违反了主键对 KEY_ID
字段的唯一性约束。
两种可能的解决方案是:
- 确保每个对象的
EventData.getId()
returns 唯一值。现在,我没有看到您将任何标识符传递给它的构造函数,也许所有事件都使用相同的id
值插入。 - 如果您不关心自己生成 ID,可以将
AUTOINCREMENT
设置添加到KEY_ID
列定义中。这样KEY_ID
字段将自动填充,每一行都有自己的唯一值。到达那里后,不要忘记自己删除将KEY_ID
添加到ContentValues
。
尝试检查该 ID 是否已存在。如果为 true,则不要插入,因为您已经有了具有此 ID 的行。
我原来放的是旧的new unique constraint infant。相反,请确保您当前的唯一列是第一个:
CREATE TABLE TEST (client_id TEXT unique, remote_id INT unique)
我的错误是,我试图填充 ID
列,尽管它已经被定义为 INTEGER PRIMARY KEY AUTOINCREMENT
使id列id整型自增,id值不放入content值中
对于使用 Room Persistence Library 的开发者。您可以使用
@Insert(onConflict = OnConflictStrategy.REPLACE) // or OnConflictStrategy.IGNORE
在 DAO 中
我遇到了同样的问题,问题是我忘记在 DbHelper
db.execSQL(YOUR_TABLE);
如果您使用 房间 那么您应该使用 @PrimaryKey(autoGenerate = true)
@PrimaryKey
并使您的 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将return新id,将其添加到您的对象
val contact = Contact(null, name, phone)
contact.id = ContactRoomDatabase.getDatabase().contactDao().insert(contact)
这是数据库中记录id重复的情况。只需清除应用程序存储空间,然后重试。一个好的解决方案是在您的 Dao class.
下方添加 @Insert (onConflict = OnConflictStrategy.REPLACE)
这个问题的正确解决方法是确保id是唯一的。请看看这个Google Codelabs Room Example
另一种避免这种情况的方法是添加 @PrimaryKey(autoGenerate = true)
对于 Kotlin 模型 类
如果您要像这样向主键分配 默认值:
data class MyModel(
@PrimaryKey(autoGenerate = true) val id: Int = defaultValue
)
确保 Long
和 Int
类型的默认值为 0
。
来自 autoGenerate
评论:
If the field type is
long
orint
(or its TypeConverter converts it to along
orint
),Insert
methods treat0
as not-set while inserting the item.
在我的例子中,我使用 -1
作为默认值并且发生了这个错误。
伙计们,我遇到了同样的问题,我从 android 设置中清除了我的本地数据库并清除了 运行 应用程序,这对我有用。也许你在数据库中做了一点改变而你忘记了。