web-dev-qa-db-de.com

Android SQLite-Ausnahme "keine solche Tabelle"

Ich fange mit SQLite und Datenbanken in Android an und habe gerade dieses Problem gefunden. Ich habe viele ähnliche Fragen gelesen, aber noch keine Lösung gefunden.

Dies ist der Fehler, den ich bekomme:

E/Android-Laufzeit (529): Ursache: Android.database.sqlite.SQLiteException: keine solche Tabelle: ligas_bd:, beim Kompilieren: SELECT * FROM ligas_bd

Das ist mein Code. 

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) { }

Ich habe auch mein Telefon mit dem Root-Explorer "data/data/mypackagename/database" eingecheckt und die Datenbank erscheint dort als normal.

Meine Datenbank und die Haupttabelle haben denselben Namen, wie Sie auf diesem Bild des SQLite-Datenbankbrowsers sehen können:

screen capture

Ich erstelle die Tabelle nicht, ich habe sie vor der Verwendung von SQLite Database Browser erstellt und versuche nur, daraus zu lesen


Ich weiß nicht wie, aber ich habe es endlich behoben. Ich habe gerade wieder angefangen, diesmal nach diesem Tutorial . Ich hoffe es hilft!

20
andoni90

Dies ist nur eine Vermutung, aber ich kann sehen, dass hier drei mögliche Dinge passieren ...

  1. Beim Aufruf von this.getReadableDatabase() in Ihrer createDatabase()-Methode wird automatisch eine leere Datenbank erstellt.
  2. Ihr Versuch, Ihre zuvor erstellte Datenbank aus Ihrem assets-Ordner zu kopieren, schlägt fehl oder die Datenbank wird an die falsche Stelle kopiert.
  3. Die in Schritt 1 (oben) erstellte leere Datenbank wird abgefragt, wenn Sie db.rawQuery(...) aus Ihrem Hauptcode aufrufen.

Um es weiter zu erklären, ist es nützlich, die Quelle für SQLiteOpenHelper zu betrachten.

Wenn Sie eine Instanz von SQLiteOpenHelper erstellen, werden Werte wie Datenbankname und -version festgelegt, die Datenbank wird jedoch nicht erstellt. Stattdessen prüft der erste Aufruf von getReadableDatabase() oder getWritableDatabase(), ob die Datenbank vorhanden ist, und erstellt sie nicht, falls nicht. Nach dem Erstellen der leeren Datenbank wird die onCreate(...)-Methode aufgerufen, die in Ihrem Fall nichts tut.

Zu Punkt 2 (oben) - Sie sagen, dass DB_PATH/data/data/mypackagename/databases ist. Wenn das wirklich der Fall ist und Sie keine /-Nachfolge haben, dann ist die Zeile ...

String myPath = DB_PATH + DB_NAME;

... setzt myPath auf /data/data/mypackagename/databasesligas_db. Selbst wenn die Kopie von assets erfolgreich ist, befindet sich die kopierte Datenbank in dem Fall nicht dort, wo sie erwartet wird.

Schließlich wird bei Punkt 3 (oben) beim Aufruf von db.rawQuery(...) die Instanz, auf die db zeigt, vom vorherigen Aufruf an getWritableDatabase() zurückgegeben. Angenommen, die Kopie von assets ist fehlgeschlagen oder wurde in den falschen Pfad kopiert, zeigt db auf die leere Datenbank, die in Schritt 1 erstellt wurde.

Der Fehler, den Sie erhalten, ist, dass die Tabelle nicht vorhanden ist und kein Fehler ist, der darauf hinweist, dass die Datenbank nicht vorhanden ist. Die einzige logische Erklärung ist, dass sie eine Abfrage für eine leere Datenbank ausführt und nicht für die Datenbank, aus der kopiert wurde assets.

EDIT: Eine andere Sache, die ich erwähnen wollte. Es ist keine gute Idee, hartcodierte Pfade zu einem der Android-Verzeichnisse zu verwenden. Zum Beispiel - obwohl auf den meisten Geräten /data/data/<package-name>/databases das Verzeichnis ist, in dem Datenbanken erstellt werden, ist dies keine Garantie. Es ist viel sicherer, wenn Sie die getDatabasePath(...)-Methode aufrufen, da ein File-Objekt zurückgegeben wird, mit dem der Pfad zum Datenbankverzeichnis abgerufen werden kann, das von den Android-Datenbankklassen verwendet wird.

19
Squonk

Ich hatte das gleiche Problem und es wurde behoben, indem das Projekt gereinigt und die App von meinem Testgerät gelöscht und erneut installiert wurde. Ich glaube, es kam vor, weil ich ein anderes Tutorial befolgt habe, bei dem versehentlich eine leere Datenbank erstellt wurde. Der korrigierte Code ruft die alte leere Datenbank ab. 

17
Logan

Wenn Sie Ihre App auf Ihrem Gerät ausführen, gehen Sie zu >> Einstellungen (auf Android-Gerät) >>> Anwendung >>> Suchen Sie Ihre Anwendung. Danach debuggen oder installieren Sie Ihre neue Anwendung erneut. 

Ich habe dieses Problem dadurch gelöst ...

12
Firhat

Die Ausnahme ist sehr klar, Sie haben die Datenbank (ligas_db) erstellt, aber keine Tabelle darin (keine solche Tabellenausnahme = keine Tabelle namens ligas_db)

Überprüfen Sie dies: http://www.vogella.de/articles/AndroidSQLite/article.html

(¿Eres Antonio Recio? Jaja)

1
Enrique Marcos

Ich hatte das gleiche Problem, die Dateinamenerweiterung .db in den Dateinamen aufzunehmen:

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

Sie haben ligas_bd als Namen der Datenbank und versuchen, SELECT von ihr auszuprobieren.

0
Abhishek Chanda

Mein Problem war, dass ich "/ database /" am Ende meines Pfadnamens gelassen habe. Was für mich so verwirrend war, ist der Code, der zuvor beim Laden einer dbconnection als Instanzvariable gespeichert wurde. Als ich dann die Methoden getReadableDatabase () und getWritableDatabase () verwenden musste, zog man die leere Datenbank, die im "echten" Datenbankpfad erstellt wurde.

INCORRECT/data/data/mypackagename/

CORRECT/data/data/mypackagename/databases/

+1 an @Squonk, dessen Antwort mir letztendlich geholfen hat, das aufzuspüren!

0
bgolson

Sie müssen zuerst eine Tabelle erstellen, bevor Sie eine Auswahl treffen. Möglicherweise haben Sie das zuvor erstellt, müssen es jedoch nach dem Öffnen der Datenbankverbindung erstellen. 

0
Dhruvisha