onDelete = NO_ACTION causes error: "SQLiteConstraintException: FOREIGN KEY constraint failed" (code 787)

onDelete = NO_ACTION causes error: "SQLiteConstraintException: FOREIGN KEY constraint failed" (code 787)

我在 SQLite 上为 Android 使用 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;
}

当我尝试从事件 table 中删除一条记录时,出现以下错误:

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,则不会出现任何问题!

我是不是漏掉了什么?

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

假设您的数据库中有 Event(1, "some event") 以及一名与会者 Attendee(1, 1)。如果事件被删除,则与会者条目将进入无效状态,因为它的外键 eventId 未指向有效条目。这就是为什么您会收到描述为 FOREIGN KEY constraint failed.

的异常的原因

onDelete = CASCADE 确保所有相关条目都将与引用的条目本身一起删除:在前面描述的情况下,当引用的事件条目 (Event(1, "some event")) 被删除。

如果你会看到 here

By default, NO_ACTION is used.

您无需明确提供。

@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 中手动删除所有指向事件 Table 行的条目- 你正在删除。