エラーの発生状況コードを書き、テーブルを定義して「実行」ボタンを押した直後、アプリがクラッシュする。これはAndroid開発における典型的な悩みです。新しいテーブルを追加したり、スキーマを変更したりしたのに、logcatには次のようなイライラさせるエラーが表示されます。
android.database.sqlite.SQLiteException: no such table: users (code 1 SQLITE_ERROR)
JavaやKotlinのファイルには確かに CREATE TABLE 文があるのに、システムはテーブルが存在しないと言い張ります。この食い違いは、デバイス上のデータベースがIDE内のコードと同期されていないために発生します。
なぜこのエラーが発生するのかAndroid OSは効率的ですが、時に頑固です。このエラーは通常、システムがデータベースのライフサイクルをどのように管理しているかに起因します。主な原因は以下の通りです。
- onCreate() の罠:
SQLiteOpenHelperのonCreate()メソッドは、データベースファイルが最初に作成される時の1回だけ実行されます。アプリがインストールされた後に「users」テーブルをコードに追加しても、onCreate()は再実行されません。古いデータベースファイルが残ったままになり、新しいテーブルが欠落した状態になります。- 古いバージョン番号: スキーマを変更したのにDATABASE_VERSION = 1のままにしている場合。この番号を上げない限り、Androidはアップデートをトリガーしません。- Roomのマイグレーションの安全性: Roomは保護的です。マイグレーションパスを提供せずに@Entityクラスを変更すると、Roomはデータの損失を避けるために、デフォルトでエラー状態になります。- 大文字小文字の区別とタイポ: SQLは一般的に大文字小文字を区別しませんが、SQLiteは複雑なクエリにおける引用符や正確な文字列の一致に厳しい場合があります。## ステップバイステップの修正方法### 1. 「クリーンアップ」アプローチ開発の初期段階で重要なユーザーデータがない場合は、複雑なマイグレーションに時間を費やす必要はありません。一度リセットしましょう。 - アプリをアンインストールする: アプリのアイコンを長押しして アンインストール を選択します。これにより、
/data/data/your.package.name/databases/にある.dbファイルが削除されます。次回の実行時に、onCreate()が新規に実行されます。- ストレージを消去する: 設定 > アプリ > [対象のアプリ] > ストレージ > データを消去 を開きます。これはフル再インストールよりも速く、同じ結果が得られます。### 2. データベースバージョンの繰り上げ標準のSQLiteOpenHelperを使用しているアプリの場合、スキーマが変更されたことをOSに知らせる必要があります。バージョンを1から2(または次の整数)に上げてください。
public class MyDatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "UserStore.db";
// onUpgrade() を実行させるために、この値を増やします
private static final int DATABASE_VERSION = 2;
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE users (id INTEGER PRIMARY KEY, username TEXT)");
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if (oldVersion < 2) {
db.execSQL("CREATE TABLE users (id INTEGER PRIMARY KEY, username TEXT)");
}
}
}
3. Roomのマイグレーション問題の解決Roomではスキーマ変更時に明示的な指示が必要です。主に2つの方法があります。
破壊的なマイグレーション(開発時のみ)バージョンが変更された場合に、古いデータベースを削除して作り直すようRoomに指示します。これにより「no such table」クラッシュは防げますが、既存のデータはすべて消去されます。
database = Room.databaseBuilder(context, MyDatabase.class, "app-db")
.fallbackToDestructiveMigration()
.build();
手動マイグレーション(本番環境)既存データを持つユーザーがいる場合は、マイグレーションオブジェクトを使用します。これにより、バージョン1から2への移行時に「users」テーブルが確実に作成されます。
static final Migration MIGRATION_1_2 = new Migration(1, 2) {
@Override
public void migrate(SupportSQLiteDatabase database) {
// テーブルが存在しない場合に作成する
database.execSQL("CREATE TABLE IF NOT EXISTS `users` (`id` INTEGER NOT NULL, `name` TEXT, PRIMARY KEY(`id`))");
}
};
Database Inspectorの活用推測はやめましょう。Android Studioの Database Inspector を使えば、デバイスのディスク上に何があるかを正確に確認できます。
- エミュレータまたは実機(API 26以上)にアプリをデプロイします。- Android Studioの下部にある App Inspection タブを開きます。- Database Inspector を選択します。- テーブル一覧を確認します。もし
usersがなければ、onCreateまたはonUpgradeのロジックが実行されていません。インスペクター内で直接SELECT * FROM usersを実行して、リアルタイムでテーブルの存在を確認することもできます。## まとめ「no such table」エラーは、ほとんどの場合バージョニングの問題です。Androidは単に既存のデータベースファイルを保護しようとしているだけです。バージョン番号を増やすか、アプリデータを消去することで、システムに新しいスキーマを認識させ、不足しているテーブルを作成させることができます。

