onDelete = NO_ACTION导致错误:“ SQLiteConstraintException:FOREIGN KEY约束失败”(代码787)

时间:2019-06-27 09:00:16

标签: android sqlite android-sqlite android-room android-database

我在Android的SQLite上使用Room,并且有以下两个Pojo实体:

@Entity
public class Event {
    @PrimaryKey
    @NonNull
    private String eventId;
    private String eventName;
}

@Entity(primaryKeys = {"eventId","attendeeId"},
        foreignKeys = {
                @ForeignKey(entity = Event.class,
                        parentColumns = "eventId",
                        childColumns = "eventId" ,onDelete = NO_ACTION)
        })
public class Attendee {
    @NonNull
    private String eventId;
    @NonNull
    private String attendeeId;
}

当我尝试从“事件”表中删除记录时,出现以下错误:

Caused by: android.database.sqlite.SQLiteConstraintException: FOREIGN KEY constraint failed (code 787) at android.database.sqlite.SQLiteConnection.nativeExecuteForChangedRowCount(Native Method)
        at android.database.sqlite.SQLiteConnection.executeForChangedRowCount(SQLiteConnection.java:732)
        at android.database.sqlite.SQLiteSession.executeForChangedRowCount(SQLiteSession.java:754)
        at android.database.sqlite.SQLiteStatement.executeUpdateDelete(SQLiteStatement.java:64)
        at android.arch.persistence.db.framework.FrameworkSQLiteStatement.executeUpdateDelete(FrameworkSQLiteStatement.java:45)
        at com.minapharm.hixspro.POJO.Room.Events.EventDao_Impl.deleteTable(EventDao_Impl.java:168)

但是,如果我将onDelete更改为CASCADE,则不会发生任何问题!

我想念什么吗?

2 个答案:

答案 0 :(得分:1)

是的。 CustomerSchema注释有助于确保条目不会进入无效状态(例如,外键不能指向不存在的条目)。

想象一下,您的数据库中有@ForeignKey,还有与会者Event(1, "some event")。如果事件被删除,那么与会者条目将进入无效状态,因为它的外键Attendee(1, 1)并不指向有效条目。这就是为什么您收到描述为eventId的异常的原因。

FOREIGN KEY constraint failed确保使用引用的条目本身擦除所有从属条目:在前述的情况下,onDelete = CASCADE也会在引用的事件条目({{1 }})被删除。

答案 1 :(得分:1)

如果您看到here

  

默认情况下,使用NO_ACTION

您不需要明确提供它。

@Entity(primaryKeys = {"eventId","attendeeId"},
        foreignKeys = {
                @ForeignKey(entity = Event.class,
                        parentColumns = "eventId",
                        childColumns = "eventId")
        })
public class Attendee {
    @NonNull
    private String eventId;
    @NonNull
    private String attendeeId;
}

此外,您需要了解数据库创建一次。您应该重新安装该应用程序,然后检查删除是否有效。

已编辑:由于您已定义ForeignKey,但未定义onDelete CASCADE,因此必须从Attendee手动删除所有指向事件表行的条目-您正在删除。