我开始研究 Android 中的 SQLite 和数据库,我刚刚发现了这个问题。我已经阅读了很多类似的问题,但我还没有找到解决方案。
这是我得到的错误:
E/AndroidRuntime(529): Caused by: 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) { }
我还使用 root explorer data/data/mypackagename/databases 检查了我的手机,数据库正常显示在那里。
我的数据库和主表同名,你可以在这张 SQLite 数据库浏览器图片中看到:
我没有创建表,我在使用 SQLite 数据库浏览器之前创建了它,我只是想从中读取
我不知道怎么办,但我终于修好了。我刚刚重新开始,这次是按照 本教程。希望能帮助到你!
原文由 andoni90 发布,翻译遵循 CC BY-SA 4.0 许可协议
这只是一个猜测,但我可以看到这里发生了三种可能的事情……
createDatabase()
方法中调用this.getReadableDatabase()
会自动创建一个空数据库。assets
文件夹复制预先创建的数据库失败或数据库被复制到错误的位置。db.rawQuery(...)
时要查询的数据库。为了进一步解释,查看 SQLiteOpenHelper 的源代码很有用
当您创建
SQLiteOpenHelper
的实例时,它会设置数据库名称和版本等内容,但不会创建数据库。相反,第一次调用getReadableDatabase()
或getWritableDatabase()
检查数据库是否存在,如果不存在则创建它。创建空数据库后,将调用onCreate(...)
方法,在您的情况下,该方法什么都不做。关于第 2 点(上图)——你说
DB_PATH
是/data/data/mypackagename/databases
。如果情况确实如此并且您没有尾随/
那么该行……将设置
myPath
为/data/data/mypackagename/databasesligas_db
。在这种情况下,即使来自assets
的复制成功,复制的数据库也不会位于您期望的位置。最后在第 3 点(上面),当您调用
db.rawQuery(...)
db
指向的实例由先前调用getWritableDatabase()
返回假设来自assets
的复制失败或它已被复制到不正确的路径,db
将指向在步骤 1 中创建的空数据库。您得到的错误是该表不存在并且它不是指示数据库不存在的错误 - 唯一合乎逻辑的解释是它正在对一个空数据库而不是从中复制的数据库执行查询
assets
。编辑:我想提的另一件事。使用任何 Android 目录的硬编码路径都不是一个好主意。例如 - 虽然在大多数设备上,创建数据库的目录将是
/data/data/<package-name>/databases
这不是保证。如果您调用getDatabasePath(...)
方法会更安全,因为它将返回一个File
对象,该对象可用于获取 Android 数据库类使用的数据库目录的路径。