SQLiteOpenHelper
onCreate()
にテーブルを作成しましたが、受け取ります
SQLiteException: no such table
または
SQLiteException: no such column
エラーどうして?
注:
(これは毎週何十もの似たような質問をまとめたものです。これらの質問がすべて良い参考文献になるように "標準的な"コミュニティウィキの質問/回答を提供しようとしています。)
SQLiteOpenHelper
onCreate()
および onUpgrade()
コールバックは、データベースが実際に開かれたときに呼び出されます。たとえば、 getWritableDatabase()
への呼び出しによって呼び出されます。データベースヘルパーオブジェクト自体が作成されても、データベースは開かれません。
SQLiteOpenHelper
はデータベースファイルをバージョン管理します。バージョン番号は、 コンストラクタに渡されるint
引数です 。データベースファイルでは、バージョン番号は PRAGMA user_version
に格納されています。
onCreate()
は、データベースファイルが存在せず、作成された直後にのみ実行されます。 onCreate()
が正常に終了した場合(例外はスローされません)、データベースは要求されたバージョン番号で作成されたと見なされます。暗黙の内に、onCreate()
の中のSQLException
sを自分で捕らえるべきではありません。
onUpgrade()
は、データベースファイルが存在するが、格納されているバージョン番号がコンストラクタで要求されたものよりも低い場合にのみ呼び出されます。 onUpgrade()
はテーブルスキーマを要求されたバージョンに更新するべきです。
テーブルスキーマをコード(onCreate()
)で変更するときは、データベースが更新されていることを確認してください。 2つの主な方法
onCreate()
が再度実行されるように古いデータベースファイルを削除します。これは開発時にインストールされているバージョンを管理でき、データの損失が問題にならない場合によく好まれます。データベースファイルを削除するいくつかの方法:
アプリケーションをアンインストールします。アプリケーションマネージャまたはシェルのadb uninstall your.package.name
を使用してください。
アプリケーションデータを消去します。アプリケーションマネージャを使用してください。
onUpgrade()
が呼び出されるようにデータベースのバージョンを増やします。より多くのコードが必要なので、これは少し複雑です。
データ損失が問題にならない開発時のスキーマアップグレードの場合は、execSQL("DROP TABLE IF EXISTS <tablename>")
inを使用して既存のテーブルを削除し、onCreate()
を呼び出してデータベースを再作成することができます。
リリースされたバージョンでは、ユーザーがデータを失うことがないように、onUpgrade()
にデータ移行を実装する必要があります。
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
および2
にbreak
ステートメントがないことに注意してください。これは私が増分アップグレードによって意味するものです。
古いバージョンが2
で、新しいバージョンが4
の場合、ロジックはデータベースを2
から3
に、そして4
にアップグレードします
古いバージョンが3
で、新しいバージョンが4
の場合、3
から4
へのアップグレードロジックを実行するだけです。
onCreate()
初めてデータベースを作成するとき(つまりデータベースが存在しないとき)onCreate()
SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)
に渡されたバージョンでデータベースを作成します
onCreate()
メソッドはあなたが定義したテーブルを作成し、あなたが書いた他のコードを実行します。ただし、このメソッドはSQLiteファイルがアプリのデータディレクトリ(/data/data/your.apps.classpath/databases
)にない場合にのみ呼び出されます。
コードを変更してエミュレータで再起動した場合、このメソッドは呼び出されません。 onCreate()
を実行したい場合は、adbを使用してSQLiteデータベースファイルを削除する必要があります。
onUpgrade()
SQLiteOpenHelper
はスーパーコンストラクターを呼び出す必要があります。onUpgrade()
メソッドは、バージョン整数がアプリで実行されている現在のバージョンよりも大きい場合にのみ呼び出されます。onUpgrade()
メソッドを呼び出したい場合は、コード内のバージョン番号を増やす必要があります。遅すぎるかもしれませんが、私の短くて甘い答えを共有したいと思います。同じ問題について 回答 を確認してください。それは間違いなくあなたを助けます。これ以上深い仕様はありません。
あなたがテーブルを作成するための構文について自信があるなら、それはあなたが同じテーブルに新しい列を追加するときに起こるかもしれません、そのために...
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
を変更することによって成功しました。)
SQLiteOpenHelper
を拡張するときに覚えておくべきポイント
super(context, DBName, null, DBversion);
- これはコンストラクタの最初の行に呼び出されるべきですonCreate
とonUpgrade
をオーバーライドします(必要な場合)。onCreate
は、getWritableDatabase()
またはgetReadableDatabase()
が実行されたときにのみ呼び出されます。そしてこれは最初のステップで指定されたDBName
が利用できないときに一度だけ呼び出されます。 onCreate
メソッドにcreate table queryを追加できますDBversion
を変更してonUpgrade
テーブルでクエリを実行するか、単にアンインストールしてからアプリをインストールします。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番目の引数として "name"文字列を指定し忘れた場合は、アプリを閉じると消去される "メモリ内"データベースが作成されます。
そのようなテーブルが見つからないのは、主に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);
}
}
Ur DatabaseHandler/DatabaseManagerクラスでクエリを再確認してください(これまでに行ったことがあります)
エミュレータまたはデバイスからアプリケーションをアンインストールします。アプリをもう一度実行します。 (データベースが既に存在する場合、OnCreate()は実行されません)
データベース名は.dbで終わっている必要があります。また、クエリ文字列にはターミネータ(;)が必要です。
Sqliteデータベースが2つの方法をオーバーライドする
1)onCreate():このメソッドは、アプリケーションの初回起動時に一度だけ呼び出されます。だからそれは一度だけ呼びました
2)onUpgrade()このメソッドは、データベースのバージョンを変更したときに呼び出され、その後このメソッドが呼び出されます。DBSchemaの作成後に新しい列を追加するなど、テーブル構造を変更するために使用されます。