Ограничения внешнего ключа в Android с использованием SQLite? Удалить каскад - PullRequest
88 голосов
/ 30 марта 2010

У меня есть две таблицы: дорожки и путевые точки, дорожка может иметь много путевых точек, но путевая точка назначается только одной дорожке.

В таблице путевых точек у меня есть столбец с именем "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"
                + " );"
              );

    ...
}

Ответы [ 9 ]

232 голосов
/ 16 июля 2010

Поддерживаются ограничения внешнего ключа при каскаде удаления, но их необходимо включить.
Я просто добавил следующее к своему SQLOpenHelper , что, похоже, помогает.

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

Я объявил свой столбец ссылок следующим образом.

mailbox_id INTEGER REFERENCES mailboxes ON DELETE CASCADE
53 голосов
/ 21 сентября 2012

Начиная с Android 4.1 (API 16) SQLiteDatabase поддерживает:

public void setForeignKeyConstraintsEnabled (boolean enable)
26 голосов
/ 22 декабря 2013

Как говорится в сообщении от e.shishkin, начиная с API 16 и выше, вы должны включить ограничения внешнего ключа в методе SqLiteOpenHelper.onConfigure(SqLiteDatabase), используя db.setForeignKeyConstraintsEnabled(boolean)

@Override
public void onConfigure(SQLiteDatabase db){
    db.setForeignKeyConstraintsEnabled(true);
}
9 голосов
/ 26 октября 2016

Никогда не слишком старый вопрос, чтобы ответить более полным ответом.

@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);
}
6 голосов
/ 18 августа 2015

Что бы ни упоминал @phil, это хорошо. Но вы можете использовать другой метод по умолчанию, доступный в Сама база данных для установки постороннего ключа. Это 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)
    }
}

Для документов см. SQLiteDatabase.setForeignKeyConstraintsEnabled

4 голосов
/ 30 марта 2010

Триггеры поддерживаются Android, и этот тип каскадного удаления не поддерживается sqlite. Пример использования триггеров на Android можно найти здесь . Хотя использование транзакций, как сказал Торстен, вероятно, так же просто, как триггер.

4 голосов
/ 30 марта 2010

Я не думаю, что SQLite поддерживает это из коробки. Что я делаю в своих приложениях:

  1. Создать транзакцию
  2. Удалить подробные данные (путевые точки в вашем примере)
  3. Удалить основные данные (дорожки в вашем примере)
  4. Подтвердить транзакцию при успехе

Таким образом, я уверен, что либо все данные удалены, либо нет.

3 голосов
/ 04 августа 2010

Версия SQLite в Android 1.6 - 3.5.9, поэтому она не поддерживает внешние ключи ...

http://www.sqlite.org/foreignkeys.html «В этом документе описана поддержка ограничений внешнего ключа SQL, введенных в SQLite версии 3.6.19.»

В Froyo это SQLite версии 3.6.22, так что ...

EDIT: посмотреть версию sqlite: adb shell sqlite3 -version

1 голос
/ 01 сентября 2011

Внешние ключи с «каскадом удаления» поддерживаются в SQLite в Android 2.2 и выше. Но будьте осторожны при их использовании: иногда сообщается об ошибке при запуске одного внешнего ключа в одном столбце, но реальная проблема заключается либо в ограничении внешнего ключа другого столбца в дочерней таблице, либо в какой-либо другой таблице, ссылающейся на эту таблицу.

Похоже, SQLite проверяет все ограничения при запуске одного из них. Это на самом деле упоминается в документации. DDL в сравнении с проверками ограничений DML.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...