自分のテーブルを作成しましたSQLiteOpenHelper
onCreate()
が、受け取りました
SQLiteException: no such table
または
SQLiteException: no such column
エラー。どうして?
注意:
(これは、毎週数十の同様の質問をまとめた要約です。これらの質問すべてを適切な参照先に送信できるように、ここに「正規」のコミュニティWiki質問/回答を提供しようとしています。)
自分のテーブルを作成しましたSQLiteOpenHelper
onCreate()
が、受け取りました
SQLiteException: no such table
または
SQLiteException: no such column
エラー。どうして?
注意:
(これは、毎週数十の同様の質問をまとめた要約です。これらの質問すべてを適切な参照先に送信できるように、ここに「正規」のコミュニティWiki質問/回答を提供しようとしています。)
回答:
SQLiteOpenHelper
onCreate()
そしてonUpgrade()
、データベースが実際の呼び出しによって、たとえば、開かれたときにコールバックが呼び出されますgetWritableDatabase()
。データベースヘルパーオブジェクト自体が作成されるとき、データベースは開かれません。
SQLiteOpenHelper
データベースファイルをバージョン管理します。バージョン番号はint
、コンストラクタに渡される引数です。データベースファイルでは、バージョン番号はに格納されていPRAGMA user_version
ます。
onCreate()
データベースファイルが存在せず、作成された直後にのみ実行されます。場合はonCreate()
リターンが正常に(例外をスローしません)、データベースが要求されたバージョン番号を使用して作成されるものとします。暗示として、SQLException
sをonCreate()
自分で捕まえてはいけません。
onUpgrade()
データベースファイルは存在するが、保存されているバージョン番号がコンストラクターで要求されたものよりも小さい場合にのみ呼び出されます。onUpgrade()
要求されたバージョンにテーブルスキーマを更新する必要があります。
コード(onCreate()
)でテーブルスキーマを変更するときは、データベースが更新されていることを確認する必要があります。2つの主なアプローチ:
古いデータベースファイルを削除して、onCreate()
再度実行します。これは多くの場合、インストール時にインストールされたバージョンを制御でき、データの損失が問題にならない開発時に推奨されます。データベースファイルを削除するいくつかの方法:
アプリケーションをアンインストールします。アプリケーションマネージャまたはadb uninstall your.package.name
シェルから使用します。
アプリケーションデータを消去します。アプリケーションマネージャを使用します。
onUpgrade()
呼び出されるようにデータベースのバージョンを増やします。より多くのコードが必要になるため、これは少し複雑になります。
データ損失が問題とならない開発時のスキーマのアップグレードの場合execSQL("DROP TABLE IF EXISTS <tablename>")
、inを使用して既存のテーブルを削除し、を呼び出しonCreate()
てデータベースを再作成できます。
リリースされたバージョンの場合onUpgrade()
、ユーザーがデータを失うことがないように、データ移行を実装する必要があります。
onUpdate()
、すべての古いバージョンを確認し、適切にデータを移行します。そして、ユーザーが自分のアプリ(古いdbファイルを持っている)を更新onUpgrade
すると、onCreate()
トリガーされ、ユーザーが新しくインストールされた場合にトリガーされます。
Jaskeyの要求に従って、ここに不足しているポイントをさらに追加するには
データベースのバージョンは、SQLite
データベースファイル内に格納されます。
catchはコンストラクタです
SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory, int version)
したがって、データベースヘルパーコンストラクターがname
(2番目のパラメーター)で呼び出されると、プラットフォームはデータベースが存在するかどうかを確認し、データベースが存在する場合は、データベースファイルヘッダーからバージョン情報を取得して、正しいコールバックをトリガーします
以前の回答ですでに説明したように、名前のデータベースが存在しない場合は、がトリガーされますonCreate
。
以下の説明ではonUpgrade
、例を挙げて説明します。
たとえば、最初のバージョンのアプリケーションにDatabaseHelper
(拡張SQLiteOpenHelper
)コンストラクターでバージョンを渡すバージョンが1
あり、バージョンがとして渡される新しいソースコードでアップグレードされたアプリケーションを提供した2
場合、DatabaseHelper
が構築onUpgrade
されると、ファイルがすでに存在することを確認することでプラットフォームがトリガーします。しかし、バージョンはあなたが渡した現在のバージョンよりも低いです。
ここで、アプリケーションの3番目のバージョンにdbバージョンを指定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);
}
}
break
case 1
との不足しているステートメントに注意してください2
。これは、インクリメンタルアップグレードの意味です。
古いバージョンがある場合を言う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()
実行するように、あなたはSQLiteデータベースファイルを削除するためにADBを使用する必要があります。
onUpgrade()
SQLiteOpenHelper
スーパーコンストラクタを呼び出す必要があります。onUpgrade()
メソッドは、バージョン整数がアプリで実行されている現在のバージョンより大きい場合にのみ呼び出されます。onUpgrade()
メソッドが呼ばれるように、あなたのコード内でバージョン番号をインクリメントする必要があります。私は遅すぎるかもしれませんが、私の短くて甘い答えを共有したいと思います。 同じ問題について回答を確認してください。それは間違いなくあなたを助けます。深い仕様はもうありません。
テーブルを作成するための構文に自信がある場合は、同じテーブルに新しい列を追加するときに発生する可能性があります...
1)デバイスからアンインストールして、もう一度実行します。
または
2)設定->アプリ-> ClearData
または
3)DATABASE_VERSION
「DatabaseHandler」クラスの変更(新しい列を追加した場合は、自動的にアップグレードされます)
public DatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
または
4)DATABASE_NAME
「DatabaseHandler」クラスを変更します(同じ問題に直面しましたが、を変更することで成功しDATABASE_NAME
ました)。
拡張時の注意点 SQLiteOpenHelper
super(context, DBName, null, DBversion);
-これはコンストラクターの最初の行を呼び出す必要がありますonCreate
およびonUpgrade
(必要な場合)onCreate
getWritableDatabase()
またはgetReadableDatabase()
が実行されたときにのみ呼び出されます。そして、これはDBName
、最初のステップで指定されたものが使用できない場合に1 回だけ呼び出されます。onCreate
メソッドにテーブル作成クエリを追加できます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をインクリメントするだけです
SQLiteデータベースは2つのメソッドをオーバーライドします
1)onCreate():このメソッドは、アプリケーションの初回起動時に1回だけ呼び出されます。だからそれは一度だけ呼びました
2)onUpgrade()このメソッドは、データベースのバージョンを変更すると呼び出され、その後、このメソッドが呼び出されます。DBスキーマの作成後に新しい列を追加するなど、テーブル構造を変更するために使用されます
このようなテーブルが見つからないのは、主にSQLiteOpenHelper
クラスを開いていない場合でgetwritabledata()
、これより前に、データベース名とバージョンを指定して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);
}
}
「名前」文字列をコンストラクタの2番目の引数として指定するのを忘れた場合は、アプリを閉じると消去される「メモリ内」データベースが作成されます。
私の場合<string-array>
、<item>
s を格納するでXMLファイルからアイテムを取得します。これら<item>
のsでは、SQL文字列を保持し、で1つずつ適用しdatabaseBuilder.addMigrations(migration)
ます。私は1つの間違いを犯しました、\
引用の前に追加するのを忘れて、例外を得ました:
android.database.sqlite.SQLiteException:そのような列はありません:some_value(コード1 SQLITE_ERROR):、コンパイル中:INSERT INTO table_name(id、name)VALUES(1、some_value)
したがって、これは正しいバリアントです:
<item>
INSERT INTO table_name(id, name) VALUES(1, \"some_value\")
</item>
Sqliteopenhelperのメソッドにはcreateとupgradeメソッドがあり、テーブルが初めて作成されるときにcreateが使用され、テーブルの列数が変更されるたびにアップグレードメソッドが呼び出されます。