android - SQLite 外键约束失败(代码 787)

标签 android sqlite foreign-keys foreign-key-relationship

我在尝试升级数据库时遇到了 Foreign Key Constraint Failed (code 787) 错误。我所做的唯一更改是尝试向我的 InsertStatus 添加第 4 个条目。我环顾四周,我读到使用 ON DELETE CASCADE 应该可以解决我的问题,所以我尝试将它放在我所有的 FK 引用中并再次尝试,但仍然是同样的问题。

Logcat 指向我的 onUpgrade 和其中的所有 DROP TABLES(我尝试一次删除一个,看看哪些是坏的,显然它们都是).

我使用 ON DELETE CASCADE 错了吗?还是我的代码中有其他内容?

插入状态

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);
}

数据库助手

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);
}

最佳答案

此处的错误与在其父实体存在之前创建子实体有关。

流程应该是:

  1. 创建父级并获取父级 ID。
  2. 创建子实体包含 引用 parent 身份

要添加更多详细信息,当您在 Room 实体上设置了 foreignKeys 数组值时,就会发生这种情况。因为您声明它将具有父列引用。如果这样做,请在尝试创建 child 之前确保您 parent 的引用有效。

因此,如果您在没有先拥有有效父 ID 的情况下创建子实体,您将抛出此 fatal error 。

关于android - SQLite 外键约束失败(代码 787),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29341380/

相关文章:

iphone - CoreData 插入还是替换?

ios - Sqlite 插入或替换不更新一列

mysql - 外键不能保持数据一致性

ruby-on-rails - 重命名foreign_key以在Rails约定中覆盖

sql - 复合外键引用2个不同的表

java - 如何以编程方式设置 TextView 的样式?

sql - 以编程方式修改 SQLite 数据库而不使用 SQL

java - gradle 依赖如何找到包?

javascript - 在webview中的html页面的javascript中捕获android软键盘按下

android - 是否有一个 Android TextVew 小部件 XML 属性从字符串的底部显示