SQLite Delete Cascade no funciona

4 minutos de lectura

Avatar de usuario de Dan14021
Dan14021

En Android 4.2, usando SQLite 3.7.11, cuando elimino una fila de la tabla Cuestionarios, cuyo esquema está debajo, las filas correspondientes en la tabla Cuestionarios no se eliminan.

No puedo entender qué está mal. he probado a poner

db.execSQL("PRAGMA foreign_keys = ON;"); 

antes y después de las declaraciones de creación de tabla.

Crear declaraciones de tabla:

CREATE TABLE quizzes(quiz_name TEXT PRIMARY KEY COLLATE NOCASE);

CREATE TABLE quizQuestions(quiz_name TEXT, question_id INTEGER,
     PRIMARY KEY(quiz_name, question_id),
     FOREIGN KEY(quiz_name) REFERENCES quizzes(quiz_name) ON DELETE CASCADE,
     FOREIGN KEY(question_id) REFERENCES questions(question_id) ON DELETE CASCADE);

  • ¿Hay algún mensaje de error? aparte de que te das cuenta de que no funciona…

    – bonCodigo

    30 de noviembre de 2012 a las 8:12

  • No, no se muestra nada en LogCat.

    – Dan14021

    30 de noviembre de 2012 a las 8:14

  • Tal vez se deba al hecho de que su clave principal es una clave compuesta… Quizás algo como esto: PRIMARY KEY (quiz_name, question_id) ON CONFLICT IGNORE, CONSTRAINT “PrimaryKey” FOREIGN KEY (“quiz_name”, “question_id”) REFERENCIAS “quizQuestions” (“quiz_name”, “question_id”) ON DELETE CASCADE);

    – bonCodigo

    30 de noviembre de 2012 a las 8:22


  • Mira esta publicación te ayudará mucho.

    – bonCodigo

    30 de noviembre de 2012 a las 8:28

  • Para mí, falló porque la tabla ya se creó sin la instrucción CASCADE, así que borre los datos de la aplicación y cree la tabla nuevamente. funcionó para mí

    – principiante

    29 de marzo de 2022 a las 13:11

avatar de usuario de zapl
zapl

Su base de datos debe eliminar filas de quizQuestions en caso de que alguien esté borrando de quizzes o de questions. Ignorará el completo restricción de clave externa en caso de que el soporte de clave externa esté desactivado y solo tenga columnas regulares que pueden contener cualquier valor.

SQLite por defecto es PRAGMA foreign_keys = OFF cada vez que usted abierto la base de datos. No es una propiedad de una tabla o del esquema.

En caso de que uses SQLiteOpenHelper ponlo adentro onOpen. Ese es el lugar al que se llama cada vez que se abre la base de datos. onCreate una sola vez cuando se crea la base de datos.


Qué SQLiteOpenHelper llama cuando llamas getWriteableDatabase por primera vez es

  1. onConfigure cada vez, se requiere nivel API >= 16
  2. dependiendo de la existencia y la versión del archivo de la base de datos, se llama a lo siguiente dentro de una transacción
    • onCreate si no hay ningún archivo de base de datos. Por lo general, esto sucede solo una vez en toda la vida útil de la aplicación.
    • onUpgrade si la versión de la base de datos (PRAGMA user_version – guardado dentro del archivo de la base de datos) es menor que la versión proporcionada en el constructor de SQLiteOpenHelper. Ocurre cada vez que cambias la versión en tu código.
    • Nada si el archivo existe y la versión coincide.
  3. onOpen cada vez

Si la misma instancia de SQLiteOpenHelper ya tiene una base de datos abierta, simplemente la devolverá y no sucederá nada de lo anterior.

Intente agregar esto justo después de abrir la base de datos en su aplicación de Android:

db.execSQL("PRAGMA foreign_keys=ON");

Esto activa el soporte para claves foráneas, que es necesario para ON DELETE CASCADE para funcionar correctamente.

  • Sí, lo estoy haciendo pero todavía no se elimina.
    Por ejemplo, db.rawQuery("INSERT INTO quizzes (quiz_name) VALUES('Test1')", null);
    db.rawQuery("INSERT INTO questions (question) VALUES('Question1')", null);
    db.rawQuery("INSERT INTO quizQuestions (quiz_name, question_id) VALUES('Test1', 1)", null);
    db.rawQuery("DELETE FROM quizzes WHERE quiz_name = 'Test1'", null);
    deja la fila Test1 en la tabla quizQuestions.

    – Dan14021

    30 de noviembre de 2012 a las 8:26


  • Parece que a partir de la API 16 (que es lo que tienes) deberías hacerlo en onConfigure() desarrollador.android.com/reference/android/database/sqlite/…

    – jugador más valioso

    30 de noviembre de 2012 a las 8:37

  • Y use db.setForeignKeyConstraintsEnabled(true) – pero la gran diferencia es: onConfigure sucede antes onCreate/onUpdate por lo que ya tiene las restricciones habilitadas allí. Por ejemplo, soltar una tabla desencadenará eliminaciones en cascada, lo que quizás no sea lo que pretendía.

    – zapl

    30 de noviembre de 2012 a las 11:43

Avatar de usuario de Ken Ratanachai S.
Ken Ratanachai S.

Sqlite deshabilita la restricción de clave externa de forma predeterminada, por lo que debe habilitarla simplemente anule el método onOpen en su clase DBhelper como se muestra a continuación

public class YourOwnDbHelper extends SQLiteOpenHelper {
    @Override
    public void onOpen(SQLiteDatabase db){
        super.onOpen(db);
        db.execSQL("PRAGMA foreign_keys=ON");
    }
}

tuve el mismo problema en visual basic!!! tienes que escribir el texto del comando así:

cone.CommandText = “PRAGMA outside_keys = ON; ELIMINAR DE empleados DONDE cod_emp=0;”

y tienes que hacerlo cada vez que borras algo

¿Ha sido útil esta solución?