AndroidにおけるSQLiteの外部キー制約とON DELETE CASCADE
AndroidにおけるSQLiteの外部キー制約とON DELETE CASCADEについて
ON DELETE CASCADEオプションは、親テーブルのレコードが削除された時に、子テーブルの関連レコードも自動的に削除する機能を提供します。このオプションは、データの整合性を保ち、複雑なSQLクエリを避けるのに役立ちます。
外部キー制約の例
例えば、ユーザーテーブルと注文テーブルがあるとします。注文テーブルには、ユーザーID列があり、ユーザーテーブルのID列を参照します。この場合、ユーザーテーブルからユーザーを削除すると、注文テーブルからそのユーザーに関連するすべての注文も自動的に削除されます。
ON DELETE CASCADEを使用する利点
- データの整合性を保ち、データの不整合を防ぐ
- 複雑なSQLクエリを避ける
- コードを簡潔にする
ON DELETE CASCADEを使用する際の注意点
- 子テーブルのレコードが誤って削除される可能性がある
- 複雑なデータ構造の場合、予期せぬ結果が発生する可能性がある
設定方法
- SQLiteOpenHelperクラスの
onCreate()
メソッドで、FOREIGN KEY
制約とON DELETE CASCADE
オプションを指定します。
public class MyOpenHelper extends SQLiteOpenHelper {
public MyOpenHelper(Context context) {
super(context, "database.db", null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE users (_id INTEGER PRIMARY KEY, name TEXT);");
db.execSQL("CREATE TABLE orders (_id INTEGER PRIMARY KEY, user_id INTEGER, FOREIGN KEY (user_id) REFERENCES users (_id) ON DELETE CASCADE);");
}
}
PRAGMA foreign_keys
をON
に設定します。
SQLiteDatabase db = getWritableDatabase();
db.execSQL("PRAGMA foreign_keys = ON;");
MyOpenHelper.java
public class MyOpenHelper extends SQLiteOpenHelper {
public MyOpenHelper(Context context) {
super(context, "database.db", null, 1);
}
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE users (_id INTEGER PRIMARY KEY, name TEXT);");
db.execSQL("CREATE TABLE orders (_id INTEGER PRIMARY KEY, user_id INTEGER, FOREIGN KEY (user_id) REFERENCES users (_id) ON DELETE CASCADE);");
}
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
private SQLiteDatabase db;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyOpenHelper helper = new MyOpenHelper(this);
db = helper.getWritableDatabase();
// データ挿入
db.execSQL("INSERT INTO users (_id, name) VALUES (1, 'John Doe');");
db.execSQL("INSERT INTO orders (_id, user_id) VALUES (1, 1);");
// ユーザー削除
db.execSQL("DELETE FROM users WHERE _id = 1;");
// 確認
Cursor cursor = db.rawQuery("SELECT * FROM orders", null);
while (cursor.moveToNext()) {
int id = cursor.getInt(0);
int userId = cursor.getInt(1);
Log.d("MainActivity", "id: " + id + ", user_id: " + userId);
}
cursor.close();
}
}
このコードを実行すると、usersテーブルからユーザーが削除されると、ordersテーブルからそのユーザーに関連するすべての注文も自動的に削除されます。
注意事項
このサンプルコードはあくまでも参考です。実際のアプリ開発では、必要に応じてコードを変更する必要があります。
ON DELETE CASCADE 以外の方法
ON DELETE RESTRICT
設定方法
db.execSQL("CREATE TABLE orders (_id INTEGER PRIMARY KEY, user_id INTEGER, FOREIGN KEY (user_id) REFERENCES users (_id) ON DELETE RESTRICT);");
注意点
このオプションを使用すると、親テーブルのレコードを削除しようとすると、SQLiteConstraintExceptionが発生する可能性があります。
ON DELETE SET NULL
ON DELETE SET NULLオプションは、親テーブルのレコードが削除された時に、子テーブルの関連レコードのuser_id
列をNULL
に設定します。
db.execSQL("CREATE TABLE orders (_id INTEGER PRIMARY KEY, user_id INTEGER, FOREIGN KEY (user_id) REFERENCES users (_id) ON DELETE SET NULL);");
このオプションを使用すると、子テーブルのレコードにNULL
値が含まれる可能性があります。
トリガーを使用して、親テーブルのレコードが削除された時に、子テーブルの関連レコードを処理することもできます。
トリガーの作成例
db.execSQL("CREATE TRIGGER delete_order_on_user_delete BEFORE DELETE ON users "
+ "FOR EACH ROW BEGIN "
+ "DELETE FROM orders WHERE user_id = OLD._id; "
+ "END;");
トリガーを使用するには、SQLiteのトリガー機能に関する知識が必要です。
どの方法を選択するべきかは、データ構造やアプリケーションの要件によって異なります。
- データの整合性を保ちたい場合は、ON DELETE RESTRICTまたはON DELETE CASCADEを使用します。
- 子テーブルのレコードに
NULL
値を含めることが許容される場合は、ON DELETE SET NULLを使用します。 - より複雑な処理が必要な場合は、トリガーを使用します。
java android sqlite