web-dev-qa-db-ja.com

Android SQLite "no such table"例外

私はSQLiteとデータベースをAndroidで始めています。この問題を見つけました。同様の質問をたくさん読みましたが、まだ解決策が見つかりませんでした。

これは私が得ているエラーです:

E/AndroidRuntime(529):原因:Android.database.sqlite.SQLiteException:no such table:ligas_bd:、コンパイル中:SELECT * FROM ligas_bd

これは私のコードです。

DBHelper myDbHelper = new DBHelper(this);
myDbHelper = new DBHelper(this);
try {
    myDbHelper.createDataBase();
} catch (IOException ioe) {
    throw new Error("Unable to create database");
}
try {
    myDbHelper.open();
    SQLiteDatabase db = null;
    db = myDbHelper.getWritableDatabase();
    String[] args = new String[] {""};
    Cursor c = db.rawQuery(" SELECT * FROM ligas_bd", args); <---- Error in this line
    if (c.moveToFirst()) {
        do {
            String cod = c.getString(0);
            String nombre = c.getString(1);
            String flag = c.getString(0);
            String cod_url = c.getString(0);
            ligas.add(new Item_Liga(nombre, flag, cod, cod_url));
        } while(c.moveToNext());
    }
}catch(SQLException sqle){
    throw sqle;
}

DBHelper.Java

public class DBHelper extends SQLiteOpenHelper{
private static String DB_NAME = "ligas_bd";
private SQLiteDatabase myDataBase;
private final Context myContext;

public DBHelper(Context context) {
    super(context, DB_NAME, null, 1);
    this.myContext = context;
}

public void createDataBase() throws IOException{
    boolean dbExist = checkDataBase();
    if(dbExist){ }
    else {
        this.getReadableDatabase();
        try {
            copyDataBase();
        } catch (IOException e) {
            throw new Error("Error copiando Base de Datos");
        }
    }
}
private boolean checkDataBase(){
    SQLiteDatabase checkDB = null;
    try {
        String myPath = DB_PATH + DB_NAME;
        checkDB = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
    } catch(SQLiteException e) { }
    if(checkDB != null) {
        checkDB.close();
    }
    return checkDB != null ? true : false;
}

private void copyDataBase() throws IOException{
    InputStream myInput = myContext.getAssets().open(DB_NAME);
    String outFileName = DB_PATH + DB_NAME;
    OutputStream myOutput = new FileOutputStream(outFileName);
    byte[] buffer = new byte[1024];
    int length;
    while ((length = myInput.read(buffer))>0) {
        myOutput.write(buffer, 0, length);
    }
    myOutput.flush();
    myOutput.close();
    myInput.close();
}

public void open() throws SQLException{
    try {
        createDataBase();
    } catch (IOException e) {
        throw new Error("Ha sido imposible crear la Base de Datos");
    }
    String myPath = DB_PATH + DB_NAME;
    myDataBase = SQLiteDatabase.openDatabase(myPath, null, SQLiteDatabase.OPEN_READONLY);
}

@Override
public synchronized void close() {
    if(myDataBase != null)
    myDataBase.close();
    super.close();
}

@Override
public void onCreate(SQLiteDatabase db) { }

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { }

また、ルートエクスプローラーのdata/data/mypackagename/databasesを使用して携帯電話をチェックインすると、データベースは通常どおり表示されます。

このデータベースとメインテーブルの名前は同じです。SQLiteデータベースブラウザーの次の写真をご覧ください。

screen capture

私はテーブルを作成しているのではなく、SQLite Database Browserを使用する前にテーブルを作成し、そこから読み取ろうとしています。


方法はわかりませんが、最終的に修正しました。今度は このチュートリアル に続いて再び始めました。それが役に立てば幸い!

20
andoni90

これは推測に過ぎませんが、3つの可能性がここで起こっていることがわかります...

  1. this.getReadableDatabase()メソッドでcreateDatabase()を呼び出すと、自動的に空のデータベースが作成されます。
  2. assetsフォルダーから作成済みのデータベースをコピーしようとして失敗したか、データベースが間違った場所にコピーされています。
  3. 手順1(上記)で作成された空のデータベースは、メインコードからdb.rawQuery(...)を呼び出したときにクエリされるデータベースです。

さらに説明するには、 SQLiteOpenHelper のソースを見ると便利です。

SQLiteOpenHelperのインスタンスを作成すると、データベース名やバージョンなどが設定されますが、データベースは作成されません。代わりに、getReadableDatabase()またはgetWritableDatabase()の最初の呼び出しは、データベースが存在するかどうかを確認し、存在しない場合は作成します。空のデータベースを作成した後、onCreate(...)メソッドが呼び出されますが、この場合は何もしません。

ポイント2(上記)-_DB_PATH_は_/data/data/mypackagename/databases_と言います。本当にそうで、末尾に_/_がない場合は、次の行を...

_String myPath = DB_PATH + DB_NAME;
_

... myPathを_/data/data/mypackagename/databasesligas_db_に設定します。その場合、assetsからのコピーが成功したとしても、コピーされたデータベースは期待した場所にはなりません。

最後にポイント3(上記)でdb.rawQuery(...)を呼び出すと、dbが指すインスタンスは、以前のgetWritableDatabase()の呼び出しによって返されます。 assetsからのコピーが失敗したか、間違ったパスにコピーされたと仮定すると、dbはステップ1で作成された空のデータベースを指します。

表示されるエラーは、テーブルが存在せず、データベースが存在しないことを示すエラーではないことです-唯一の論理的な説明は、コピー元のデータベースではなく空のデータベースでクエリを実行していることですassets

編集:私が言及したいもう一つのこと。 Androidディレクトリのいずれかにハードコードされたパスを使用することはお勧めできません。たとえば、ほとんどのデバイスでは、データベースが作成されるディレクトリは_/data/data/<package-name>/databases_になりますが、これは保証ではありません。 Androidが使用するデータベースディレクトリへのパスを取得するために使用できるFileオブジェクトを返すため、getDatabasePath(...)メソッドを呼び出すと、はるかに安全です。データベースクラス。

19
Squonk

同じ問題が発生したため、プロジェクトをクリーンアップし、テストデバイスからアプリを削除して再インストールすることで修正しました。誤って空のデータベースを作成した別のチュートリアルを実行したために発生したと考えています。修正されたコードは、古い空のデータベースを取得していました。

18
Logan

デバイスでアプリを実行している場合は、>>設定(Androidデバイス)>>>アプリケーション>>>アプリケーションの検索>>データとキャッシュをクリアします。その後、デバッグに移動します。または、新しいアプリケーションを再インストールします。

私はそれをすることでこの問題を解決しました...

12
Firhat

例外は非常に明確で、データベース(ligas_db)を作成しましたが、その中にテーブルは作成していません(そのようなテーブル例外はありません= ligas_dbという名前のテーブルはありません)

これを確認してください: http://www.vogella.de/articles/AndroidSQLite/article.html

(¿Eres Antonio Recio?jaja)

1
Enrique Marcos

ファイル名に.db拡張子を含めると同じ問題が発生しました:

private static String DB_NAME = "ligas_bd.db";
0
Uğur Dinç

あなたが持っている ligas_bdをデータベースの名前として使用し、SELECTから取得しようとしています。

0
Abhishek Chanda

私の問題は、パス名の末尾に「/ databases /」を残したことです。私にとって非常に紛らわしかったのは、dbconnectionをロードしてインスタンス変数として保存する前に動作していたコードです。次に、getReadableDatabase()メソッドとgetWritableDatabase()メソッドを使用する必要があるとき、「実際の」データベースパスに作成された空のデータベースを引き込み続けました。

誤り/ data/data/mypackagename /

正しい/ data/data/mypackagename/databases /

答えの@Squonkに+1することで、ついにこれを追跡することができました!

0
bgolson

テーブルを選択する前に、まずテーブルを作成する必要があります。以前に作成したことがありますが、データベース接続を開いた後に作成する必要があります。

0
Dhruvisha