私の Android アプリケーションには、外部キーのデータベース関係に関連する奇妙な問題があります。次のコードは、私の単純なデータベースの構造を説明しています。データベース操作を処理するためのスーパークラスとして SQLiteOpenHelper を使用しました。
private static final String CATEGORIES_TABLE = "CREATE TABLE __CATEGORIES_TBL(_id INTEGER PRIMARY KEY AUTOINCREMENT, _name TEXT NOT NULL, _desc TEXT NULL,"
+ "_create_date INTEGER NOT NULL, _update_date INTEGER NULL"
+ ", _parent_id INTEGER NULL, FOREIGN KEY(_parent_id) REFERENCES __CATEGORIES_TBL(_id) ON DELETE RESTRICT);";
private static final String CARDS_TABLE = "CREATE TABLE __CARDS_TBL(_id INTEGER PRIMARY KEY AUTOINCREMENT,"
+ "_value TEXT NOT NULL, _play_count INTEGER NULL, "
+ "_category_id INTEGER NOT NULL, FOREIGN KEY(_category_id) REFERENCES __CATEGORIES_TBL(_id) ON DELETE RESTRICT);";
@Override
public void onCreate(SQLiteDatabase db) {
try {
db.execSQL("PRAGMA foreign_keys = ON;");
db.execSQL(CATEGORIES_TABLE);
db.execSQL(CARDS_TABLE);
Logger.i("DB-INIT-DONE!");
} catch (Exception ex) {
Logger.e("Database on create error", ex);
}
}
ご覧のとおり、すべて問題ないようです。両方のテーブルに対して行を挿入、編集、選択できますが、残念ながら、子行を持つ行を削除できます。私の期待通りに。ON DELETE RESTRICT モードで 2 つのテーブル間に FK (外部キー) 関係を設定しているため、親テーブル (__CATEGORIES_TBL) から行を削除しようとすると例外が発生することが予想されますが、実際には親レコードが削除され、例外は発生しません。起こる、
理論上、sqlite は、__CARDS_TBL に 1 つ以上の子行がある場合、または __CATEGORIES_TBL に子行がある場合、__CATEGORIES_TBL の行を削除しないようにする必要がありますが、私のアプリケーションでは、親子関係の行がある場合に行を削除できます。
次のコードを検討してください(これは削除コードです)
private SQLiteDatabase db;
public long delete(long objId) {
try {
// TABLE_NAME can be __CATEGORIES_TBL or __CARDS_TBL based on program flow
return db.delete(TABLE_NAME, COLUMN_ROWID + "=" + objId, null);
} catch (Exception e) {
Logger.d("Unable to delete category <" + objId + ">.", e);
return -123456;
}
}
db.delete を呼び出すたびに 1 が返されます (このコマンドによって 1 行が削除されることを意味します)。このコードは android 2.3 で実行されています。
前もって感謝します。