web-dev-qa-db-ja.com

SQLiteOpenHelper onCreate()/ onUpgrade()はいつ実行されますか?

SQLiteOpenHelperonCreate()にテーブルを作成しましたが、受け取ります

SQLiteException: no such table

または

SQLiteException: no such column

エラーどうして?

注:

(これは毎週何十もの似たような質問をまとめたものです。これらの質問がすべて良い参考文献になるように "標準的な"コミュニティウィキの質問/回答を提供しようとしています。)

277
laalto

SQLiteOpenHelperonCreate() および onUpgrade() コールバックは、データベースが実際に開かれたときに呼び出されます。たとえば、 getWritableDatabase() への呼び出しによって呼び出されます。データベースヘルパーオブジェクト自体が作成されても、データベースは開かれません。

SQLiteOpenHelperはデータベースファイルをバージョン管理します。バージョン番号は、 コンストラクタに渡されるint引数です 。データベースファイルでは、バージョン番号は PRAGMA user_version に格納されています。

onCreate()は、データベースファイルが存在せず、作成された直後にのみ実行されます。 onCreate()が正常に終了した場合(例外はスローされません)、データベースは要求されたバージョン番号で作成されたと見なされます。暗黙の内に、onCreate()の中のSQLExceptionsを自分で捕らえるべきではありません。

onUpgrade()は、データベースファイルが存在するが、格納されているバージョン番号がコンストラクタで要求されたものよりも低い場合にのみ呼び出されます。 onUpgrade()はテーブルスキーマを要求されたバージョンに更新するべきです。

テーブルスキーマをコード(onCreate())で変更するときは、データベースが更新されていることを確認してください。 2つの主な方法

  1. onCreate()が再度実行されるように古いデータベースファイルを削除します。これは開発時にインストールされているバージョンを管理でき、データの損失が問題にならない場合によく好まれます。データベースファイルを削除するいくつかの方法:

    • アプリケーションをアンインストールします。アプリケーションマネージャまたはシェルのadb uninstall your.package.nameを使用してください。

    • アプリケーションデータを消去します。アプリケーションマネージャを使用してください。

  2. onUpgrade()が呼び出されるようにデータベースのバージョンを増やします。より多くのコードが必要なので、これは少し複雑です。

    • データ損失が問題にならない開発時のスキーマアップグレードの場合は、execSQL("DROP TABLE IF EXISTS <tablename>") inを使用して既存のテーブルを削除し、onCreate()を呼び出してデータベースを再作成することができます。

    • リリースされたバージョンでは、ユーザーがデータを失うことがないように、onUpgrade()にデータ移行を実装する必要があります。

342
laalto

Jaskeyのリクエストに応じて、ここに不足ポイントをさらに追加するには

データベースバージョンはSQLiteデータベースファイル内に保存されます。

catchはコンストラクタです

SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)

したがって、データベースヘルパーコンストラクターがname(2番目のパラメーター)で呼び出されると、プラットフォームはデータベースが存在するかどうかを確認し、データベースが存在する場合、データベースファイルヘッダーからバージョン情報を取得し、正しいコールバックをトリガーします

以前の回答で既に説明したように、名前を持つデータベースが存在しない場合、onCreateをトリガーします。

以下の説明では、onUpgradeケースを例とともに説明します。

アプリケーションの最初のバージョンには、DatabaseHelper(拡張SQLiteOpenHelper)があり、バージョンを1として渡すコンストラクターがあり、その後、バージョンが2、そしてDatabaseHelperが構築されると自動的にプラットフォームはonUpgradeをトリガーしますが、ファイルは既に存在しますが、バージョンは渡した現在のバージョンよりも低くなります。

ここで、dbバージョンが3であるアプリケーションの3番目のバージョンを提供する予定であると言います(dbバージョンは、データベーススキーマを変更する場合にのみ増加します)。このようなインクリメンタルアップグレードでは、メンテナンスしやすいコードを作成するために、各バージョンからアップグレードロジックをインクリメンタルに記述する必要があります。

以下の擬似コードの例:

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
  switch(oldVersion) {
    case 1:
       //upgrade logic from version 1 to 2
    case 2:
       //upgrade logic from version 2 to 3
    case 3:
       //upgrade logic from version 3 to 4
       break;
    default:
       throw new IllegalStateException(
                "onUpgrade() with unknown oldVersion " + oldVersion);
  }
}

Case 1および2breakステートメントがないことに注意してください。これは私が増分アップグレードによって意味するものです。

古いバージョンが2で、新しいバージョンが4の場合、ロジックはデータベースを2から3に、そして4にアップグレードします

古いバージョンが3で、新しいバージョンが4の場合、3から4へのアップグレードロジックを実行するだけです。

96
Aun

onCreate()

  1. 初めてデータベースを作成するとき(つまりデータベースが存在しないとき)onCreate()SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)に渡されたバージョンでデータベースを作成します

  2. onCreate()メソッドはあなたが定義したテーブルを作成し、あなたが書いた他のコードを実行します。ただし、このメソッドはSQLiteファイルがアプリのデータディレクトリ(/data/data/your.apps.classpath/databases)にない場合にのみ呼び出されます。

  3. コードを変更してエミュレータで再起動した場合、このメソッドは呼び出されません。 onCreate()を実行したい場合は、adbを使用してSQLiteデータベースファイルを削除する必要があります。

onUpgrade()

  1. SQLiteOpenHelperはスーパーコンストラクターを呼び出す必要があります。
  2. onUpgrade()メソッドは、バージョン整数がアプリで実行されている現在のバージョンよりも大きい場合にのみ呼び出されます。
  3. onUpgrade()メソッドを呼び出したい場合は、コード内のバージョン番号を増やす必要があります。
20
jeet parmar

遅すぎるかもしれませんが、私の短くて甘い答えを共有したいと思います。同じ問題について 回答 を確認してください。それは間違いなくあなたを助けます。これ以上深い仕様はありません。

あなたがテーブルを作成するための構文について自信があるなら、それはあなたが同じテーブルに新しい列を追加するときに起こるかもしれません、そのために...

1)お使いのデバイスからアンインストールして、もう一度実行してください。

OR

2)設定 - >アプリ - > ClearData

OR

3)あなたの "DatabaseHandler"クラスのDATABASE_VERSIONを変更してください(自動的にアップグレードされるより新しい列を追加した場合)

public DatabaseHandler(Context context) {
    super(context, DATABASE_NAME, null, DATABASE_VERSION);
}

OR

4)あなたの "DatabaseHandler"クラスのDATABASE_NAMEを変更します(私は同じ問題に直面しました。しかし私はDATABASE_NAMEを変更することによって成功しました。)

9
Kush

SQLiteOpenHelperを拡張するときに覚えておくべきポイント

  1. super(context, DBName, null, DBversion); - これはコンストラクタの最初の行に呼び出されるべきです
  2. onCreateonUpgradeをオーバーライドします(必要な場合)。
  3. onCreateは、getWritableDatabase()またはgetReadableDatabase()が実行されたときにのみ呼び出されます。そしてこれは最初のステップで指定されたDBNameが利用できないときに一度だけ呼び出されます。 onCreateメソッドにcreate table queryを追加できます
  4. 新しいテーブルを追加したいときはいつでもDBversionを変更してonUpgradeテーブルでクエリを実行するか、単にアンインストールしてからアプリをインストールします。
4
JibinNajeeb

onCreateは、テーブルの作成が必要なときに初めて呼び出されます。 SQLiteDatabaseによって実行されるテーブル作成用のスクリプトを記述する場所でこのメソッドをオーバーライドする必要があります。 execSQLメソッド初回のデプロイで実行した後は、このメソッドは今後呼び出されません。

onUpgradeデータベースのバージョンアップ時に呼び出されます。最初の配置で、データベースのバージョンが1で、2番目の配置で、テーブルに列を追加するなどのデータベース構造の変更があったとします。データベースのバージョンが2だとします。

あなたは以下のようにデータベースとテーブルを作成できます。

public class DbHelper extends SQLiteOpenHelper {
private static final String DBNAME = "testdatbase.db";
private static final int VERSION = 1;

public DbHelper(Context context) {
    super(context, DBNAME, null, VERSION);
    // TODO Auto-generated constructor stub
}

@Override
public void onCreate(SQLiteDatabase db) {
    // TODO Auto-generated method stub
    db.execSQL("create table BookDb(id integer primary key autoincrement,BookName text,Author text,IssuedOn text,DueDate text,Fine text,Totalfine text");

}

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    db.execSQL("DROP TABLE IF EXISTS BookDb");
    onCreate(db);
  }
}

注:他のテーブルを作成したり、列を追加したり、そのようなテーブルを追加したりしたくない場合は、VERSIONを増分してください

2
Enamul Haque

コンストラクタへの2番目の引数として "name"文字列を指定し忘れた場合は、アプリを閉じると消去される "メモリ内"データベースが作成されます。

1
phreakhead

そのようなテーブルが見つからないのは、主にgetwritabledata()SQLiteOpenHelperクラスを開いていないときで、その前に、databasename&versionでmakeコンストラクターを呼び出す必要もありません。そしてOnUpgradeクラスで与えられたバージョン番号にアップグレード値があるときはいつでもSQLiteOpenHelperが呼び出されます。

以下はコードスニペットです(そのような列が見つからないのは、列名のスペルが原因の可能性があります)。

public class database_db {
    entry_data endb;
    String file_name="Record.db";
    SQLiteDatabase sq;
    public database_db(Context c)
    {
        endb=new entry_data(c, file_name, null, 8);
    }
    public database_db open()
    {
        sq=endb.getWritableDatabase();
        return this;
    }
    public Cursor getdata(String table)
    {
        return sq.query(table, null, null, null, null, null, null);
    }
    public long insert_data(String table,ContentValues value)
    {
        return sq.insert(table, null, value);
    }
    public void close()
    {
        sq.close();
    }
    public void delete(String table)
    {
        sq.delete(table,null,null);
    }
}
class entry_data extends SQLiteOpenHelper
{

    public entry_data(Context context, String name, SQLiteDatabase.CursorFactory factory,
                      int version) {
        super(context, name, factory, version);
        // TODO Auto-generated constructor stub
    }

    @Override
    public void onCreate(SQLiteDatabase sqdb) {
        // TODO Auto-generated method stub

        sqdb.execSQL("CREATE TABLE IF NOT EXISTS 'YOUR_TABLE_NAME'(Column_1 text not null,Column_2 text not null);");

    }

    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
          onCreate(db);
    }

}
1
Bharat Lalwani

Ur DatabaseHandler/DatabaseManagerクラスでクエリを再確認してください(これまでに行ったことがあります)

0
venu

エミュレータまたはデバイスからアプリケーションをアンインストールします。アプリをもう一度実行します。 (データベースが既に存在する場合、OnCreate()は実行されません)

0
Nand gopal

データベース名は.dbで終わっている必要があります。また、クエリ文字列にはターミネータ(;)が必要です。

0
Omer Haqqani

Sqliteデータベースが2つの方法をオーバーライドする

1)onCreate():このメソッドは、アプリケーションの初回起動時に一度だけ呼び出されます。だからそれは一度だけ呼びました

2)onUpgrade()このメソッドは、データベースのバージョンを変更したときに呼び出され、その後このメソッドが呼び出されます。DBSchemaの作成後に新しい列を追加するなど、テーブル構造を変更するために使用されます。

0