web-dev-qa-db-fra.com

Contraintes de clé étrangère dans Android utilisant SQLite? Sur la cascade de suppression

J'ai deux tableaux: les traces et les waypoints, une trace peut avoir plusieurs waypoints, mais un waypoint est assigné à seulement 1 trace.

Dans la table des points de chemin, j'ai une colonne appelée "trackidfk" qui insère le track_ID une fois qu'une piste est faite, mais je n'ai pas configuré de contraintes de clé étrangère sur cette colonne.

Lorsque je supprime une piste, je veux supprimer les waypoints attribués, est-ce possible?. J'ai lu sur l'utilisation des déclencheurs mais je ne pense pas qu'ils soient pris en charge dans Android.

Pour créer la table des waypoints:

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"
                + " );"
              );

    ...
}
89
jcrowson

Les contraintes de clé étrangère avec cascade de suppression sont prises en charge, mais vous devez les activer.
Je viens d'ajouter ce qui suit à mon SQLOpenHelper, ce qui semble faire l'affaire.

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

J'ai déclaré ma colonne de référencement comme suit.

mailbox_id INTEGER REFERENCES mailboxes ON DELETE CASCADE
234
Phil

Depuis Android 4.1 (API 16) SQLiteDatabase prend en charge:

public void setForeignKeyConstraintsEnabled (boolean enable)
53
e.shishkin

Comme le dit e.shishkin à partir de l'API 16, vous devez activer les contraintes de clé étrangère dans la méthode SqLiteOpenHelper.onConfigure(SqLiteDatabase) en utilisant la fonction db.setForeignKeyConstraintsEnabled(boolean)

@Override
public void onConfigure(SQLiteDatabase db){
    db.setForeignKeyConstraintsEnabled(true);
}
26
malcolm

Jamais trop vieux d'une question pour répondre avec une réponse plus complète.

@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);
}
9
Codeversed

Quel que soit @phil mentionné est bon. Mais vous pouvez utiliser une autre méthode par défaut disponible dans Database elle-même pour définir la clé étrangère. C'est 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)
    }
}

Pour les documents, reportez-vous à SQLiteDatabase.setForeignKeyConstraintsEnabled

6
anand krish

Les déclencheurs sont pris en charge par Android et ce type de suppression en cascade n'est pas pris en charge par sqlite. Un exemple d'utilisation des déclencheurs sur Android peut être trouvé ici . Bien que l'utilisation de transactions comme Thorsten l'a déclaré soit probablement aussi simple qu'un déclencheur.

4
Dave.B

Je ne pense pas que SQLite le prenne en charge. Ce que je fais dans mes applications, c'est:

  1. Créer une transaction
  2. Supprimer les données détaillées (waypoints dans votre exemple)
  3. Supprimer les données de base (pistes dans votre exemple)
  4. Valider la transaction en cas de succès

De cette façon, je suis sûr que toutes les données sont supprimées ou aucune.

4
Thorsten Dittmar

Version SQLite en Android 1.6 est 3.5.9 donc il ne prend pas en charge les clés étrangères ...

http://www.sqlite.org/foreignkeys.html "Ce document décrit la prise en charge des contraintes de clé étrangère SQL introduites dans SQLite version 3.6.19."

Dans Froyo c'est SQLite version 3.6.22, donc ...

EDIT: pour voir la version sqlite: adb Shell sqlite3 -version

3
GBouerat

Les clés étrangères avec "on delete cascade" sont prises en charge dans SQLite dans Android 2.2 et plus. Mais soyez prudent lorsque vous les utilisez: parfois une erreur est signalée lors du lancement d'une clé étrangère sur une colonne, mais le vrai problème réside soit dans une autre contrainte de clé étrangère de colonne dans la table enfant, soit dans une autre table qui référence cette table.

On dirait que SQLite vérifie toutes les contraintes lors du lancement de l'une d'entre elles. Il est en fait mentionné dans la documentation. Vérifications des contraintes DDL et DML.

1
Yar