Android中使用SQLite的外键约束?在删除级联

jcr*_*son 90 java sqlite android foreign-keys

我有两个表:轨道和航点,一个轨道可以有很多航点,但一个航点只分配给一个轨道.

在点数表中,我有一个名为"trackidfk"的列,它在制作轨道时插入track_ID,但是我没有在此列上设置外键约束.

当我删除一条轨道时,我想删除指定的路标,这可能吗?我读过有关使用触发器的内容,但我不认为它们在Android中受支持.

要创建航点表:

public void onCreate(SQLiteDatabase db) {
    db.execSQL( "CREATE TABLE " + TABLE_NAME 
                + " (" 
                + _ID         + " INTEGER PRIMARY KEY AUTOINCREMENT, " 
                + LONGITUDE   + " INTEGER," 
                + LATITUDE    + " INTEGER," 
                + TIME        + " INTEGER,"
                + TRACK_ID_FK + " INTEGER"
                + " );"
              );

    ...
}
Run Code Online (Sandbox Code Playgroud)

Phi*_*hil 236

支持使用on delete cascade的外键约束,但您需要启用它们.
我刚刚将以下内容添加到我的SQLOpenHelper中,这似乎可以解决问题.

@Override
public void onOpen(SQLiteDatabase db) {
    super.onOpen(db);
    if (!db.isReadOnly()) {
        // Enable foreign key constraints
        db.execSQL("PRAGMA foreign_keys=ON;");
    }
}
Run Code Online (Sandbox Code Playgroud)

我将我的引用列声明如下.

mailbox_id INTEGER REFERENCES mailboxes ON DELETE CASCADE
Run Code Online (Sandbox Code Playgroud)

  • 这意味着它只适用于Android 2.2 Froyo,它有SQLite 3.6.22 (58认同)
  • 作为评论:这仅适用于sqlite版本3.6.19. (32认同)
  • Google建议在[`onConfigure()`](http://developer.android.com/reference/android/database/sqlite/SQLiteOpenHelper.html#onConfigure(android.database.sqlite.SQLiteDatabase))中编写`PRAGMA`语句,但它需要API级别16(Android 4.1),然后你可以简单地调用[`setForeignKeyConstraintsEnabled`](http://stackoverflow.com/a/12531927/1402846). (12认同)
  • @Phil,你为什么使用if-read-only条件? (2认同)

e.s*_*kin 53

由于Android 4.1(API 16)SQLiteDatabase支持:

public void setForeignKeyConstraintsEnabled (boolean enable)
Run Code Online (Sandbox Code Playgroud)


小智 26

正如e.shishkin的帖子从API 16开始说的那样,你应该在SqLiteOpenHelper.onConfigure(SqLiteDatabase)方法中启用外键约束db.setForeignKeyConstraintsEnabled(boolean)

@Override
public void onConfigure(SQLiteDatabase db){
    db.setForeignKeyConstraintsEnabled(true);
}
Run Code Online (Sandbox Code Playgroud)


Cod*_*sed 9

用更完整的答案回答问题永远不会过于陈旧.

@Override public void onOpen(SQLiteDatabase db) {
    super.onOpen(db);
    if (!db.isReadOnly()) {
        setForeignKeyConstraintsEnabled(db);
    }
    mOpenHelperCallbacks.onOpen(mContext, db);
}

private void setForeignKeyConstraintsEnabled(SQLiteDatabase db) {
    if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
        setForeignKeyConstraintsEnabledPreJellyBean(db);
    } else {
        setForeignKeyConstraintsEnabledPostJellyBean(db);
    }
}

private void setForeignKeyConstraintsEnabledPreJellyBean(SQLiteDatabase db) {
    db.execSQL("PRAGMA foreign_keys=ON;");
}

@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
private void setForeignKeyConstraintsEnabledPostJellyBean(SQLiteDatabase db) {
    db.setForeignKeyConstraintsEnabled(true);
}
Run Code Online (Sandbox Code Playgroud)


ana*_*ish 6

无论@phil提到什么都是好的.但您可以使用Database自身中可用的另一种默认方法来设置外键.那就是setForeignKeyConstraintsEnabled(true).

@Override
public void onOpen(SQLiteDatabase db) {
    super.onOpen(db);
    if (!db.isReadOnly()) {
        // Enable foreign key constraints
        db.execSQL("PRAGMA foreign_keys=ON;"); 
              //(OR)
        db.setForeignKeyConstraintsEnabled (true)
    }
}
Run Code Online (Sandbox Code Playgroud)

对于Docs,请参阅SQLiteDatabase.setForeignKeyConstraintsEnabled

  • 您发布的文档建议:`调用此方法的好时机是在调用openOrCreateDatabase(File,SQLiteDatabase.CursorFactory)或onConfigure(SQLiteDatabase)回调之后.因此,而不是`onOpen`,`onConfigure`似乎是正确的地点. (3认同)