我尝试升级数据库时遇到Foreign Key Constraint Failed (code 787)
错误。我做的唯一改变是尝试在InsertStatus
添加第4个条目。我环顾四周,我读到使用ON DELETE CASCADE
应该解决我的问题,所以我尝试将它放在我所有的FK引用上并再次尝试,但仍然是同样的问题。
Logcat指向我的onUpgrade
以及其中的所有DROP TABLES
(我尝试一次删除一个,看看哪些是坏的,显然所有都是坏的)。
我使用ON DELETE CASCADE
错了吗?或者我的代码中还有其他内容?
InsertStatus
void InsertStatus(SQLiteDatabase db) {
ContentValues cv = new ContentValues();
cv.put(colStatusID, 0);
cv.put(colStatClass, "Active");
db.insert(statTable, colStatusID, cv);
cv.put(colStatusID, 1);
cv.put(colStatClass, "Settled");
db.insert(statTable, colStatusID, cv);
cv.put(colStatusID, 2);
cv.put(colStatClass, "Terminated");
db.insert(statTable, colStatusID, cv);
cv.put(colStatusID, 3);
cv.put(colStatClass, "");
db.insert(statTable, colStatusID, cv);
}
DatabaseHelper
db.execSQL("CREATE TABLE " + termsTable + " (" + colTermsID + " INTEGER PRIMARY KEY , " + colTermsClass + " TEXT)");
db.execSQL("CREATE TABLE " + periodTable + " (" + colPeriodID + " INTEGER PRIMARY KEY , " + colPeriodClass + " TEXT)");
db.execSQL("CREATE TABLE " + statTable + " (" + colStatusID + " INTEGER PRIMARY KEY , " + colStatClass + " TEXT)");
db.execSQL("CREATE TABLE " + accountsTable + " (" + colID + " INTEGER PRIMARY KEY AUTOINCREMENT, " +
colName + " TEXT, " +
colAmount + " Integer, " +
colPurpose + " TEXT, " +
colTerms + " INTEGER NOT NULL, " +
colPeriod +" INTEGER NOT NULL, " +
colBalance +" INTEGER, "+
colStatus + " INTEGER DEFAULT '1'," +
colDate + " TEXT, " +
colEditDate + " TEXT, " +
"FOREIGN KEY (" + colTerms + ") REFERENCES " + termsTable + " (" + colTermsID + ") ON DELETE CASCADE," +
"FOREIGN KEY (" + colPeriod + ") REFERENCES " + periodTable + " (" + colPeriodID + ") ON DELETE CASCADE," +
"FOREIGN KEY (" + colStatus + ") REFERENCES " + statTable + " (" + colStatusID + ") ON DELETE CASCADE);");
db.execSQL("CREATE TABLE " + payTable + " (" + colPayID + " INTEGER PRIMARY KEY , " +
colGroupID + " INTEGER NOT NULL, " +
colPayBal + " TEXT, " +
colInterest + " TEXT, " +
colPayDue + " TEXT, " +
colDateDue + " TEXT, " +
colPaid + " Integer, " +
"FOREIGN KEY (" + colGroupID + ") REFERENCES " + accountsTable + " (" + colID + ") ON DELETE CASCADE);");
db.execSQL("CREATE VIEW " + viewAccs +
" AS SELECT " + accountsTable + "." + colID + " AS _id," +
" " + accountsTable + "." + colName + "," +
" " + accountsTable + "." + colAmount + "," +
" " + accountsTable + "." + colPurpose + "," +
" " + termsTable + "." + colTermsClass + "," +
" " + periodTable + "." + colPeriodClass + "," +
" " + accountsTable+ "." + colBalance + "," +
" " + statTable + "." + colStatClass + "," +
" " + accountsTable + "." + colDate + "," +
" " + accountsTable + "." + colEditDate + "" +
" FROM " + accountsTable +
" JOIN " + termsTable + " ON " + accountsTable + "." + colTerms + " = " + termsTable + "." + colTermsID +
" JOIN " + periodTable + " ON " + accountsTable + "." + colPeriod + " = " + periodTable + "." + colPeriodID +
" JOIN " + statTable + " ON " + accountsTable + "." + colStatus + " = " + statTable + "." + colStatusID );
db.execSQL("CREATE VIEW " + viewPmnts +
" AS SELECT " + payTable + "." + colPayID + " AS _id," +
" " + accountsTable + "." + colID + "," +
" " + payTable + "." + colGroupID + "," +
" " + payTable + "." + colPayBal + "," +
" " + payTable + "." + colInterest + "," +
" " + payTable + "." + colPayDue + "," +
" " + payTable + "." + colDateDue + "," +
" " + payTable + "." + colPaid + "" +
" FROM " + payTable +
" JOIN " + accountsTable + " ON " + payTable + "." + colGroupID + " = " + accountsTable + "." + colID );
InsertTerms(db);
InsertPeriods(db);
InsertStatus(db);
}
onUpgrade
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + accountsTable);
db.execSQL("DROP TABLE IF EXISTS " + termsTable);
db.execSQL("DROP TABLE IF EXISTS " + periodTable);
db.execSQL("DROP TABLE IF EXISTS " + statTable);
db.execSQL("DROP TABLE IF EXISTS " + payTable);
db.execSQL("DROP TRIGGER IF EXISTS acc_id_trigger");
db.execSQL("DROP TRIGGER IF EXISTS acc_id_trigger22");
db.execSQL("DROP TRIGGER IF EXISTS fk_accterm_termid");
db.execSQL("DROP TRIGGER IF EXISTS fk_accperiod_periodid");
db.execSQL("DROP TRIGGER IF EXISTS fk_accpay_payid");
db.execSQL("DROP TRIGGER IF EXISTS fk_accstat_statid");
db.execSQL("DROP VIEW IF EXISTS " + viewAccs);
db.execSQL("DROP VIEW IF EXISTS " + viewPmnts);
onCreate(db);
}
答案 0 :(得分:8)
根据以下链接,您插入未通过外键约束的值意味着您添加了父表中不存在的foregin键值
答案 1 :(得分:2)
此处的错误与在父级存在之前创建子级实体有关。
流应为:
-创建父级并获取父级ID。 ----创建包含对父ID的引用的子实体。
因此,如果您在未先具有有效父代ID的情况下创建子实体,则会引发此致命错误。
答案 2 :(得分:1)
就我而言,我忘记用数据填充父表。将项目添加到子表时,出现此错误。当删除实体文件中的bfg --delete-files YOUR-FILE-WITH-UNWANTED-DATA
行时:
foreignKeys
插入成为可能。 (但是,如果您这样做却不清除应用程序数据,则会出现异常foreignKeys = [
ForeignKey(entity = SomeEntity::class, parentColumns = ["id"], childColumns = ["parent_id"]),
...
]
)
因此,只需将必要的数据添加到父表中即可。
更新
我又遇到了这个异常。
为了测试哪个外键冲突,请注释其中几个并重新编译应用程序。还要删除已安装的文件或擦除其数据。启动应用程序后,照常执行请求。如果没有异常,请取消注释一个外键。然后再次删除该应用程序,重新编译,然后将数据添加到表中。直到知道违反哪个外键为止。
在我的情况下,我在列中插入了java.lang.IllegalStateException: Room cannot verify the data integrity. Looks like you've changed schema but forgot to update the version number. You can simply fix this by increasing the version number.
而不是0
,以便父表不包含null
。
答案 3 :(得分:0)
确保首先插入父表中的对象。在进行一些测试时,我在犯同样的错误(没有添加相应的父项,因此父表中的PK不存在。)
希望能解决您的问题。
答案 4 :(得分:0)
在我的情况下,问题是我使用了
@Insert(onConflict = OnConflictStrategy.REPLACE)
代替
@Update
在@Dao中。
答案 5 :(得分:0)
获取错误“外键约束失败(代码787)”的另一种方法是,如果表“ Alpha”具有指向表“ Beta”的外键,并且您尝试在Alpha数据之前删除Beta的数据。应该向后做。