我们的应用程序中有一个 sqlite 数据库。它对所有用户来说都工作正常,但很少有人遇到
Caused by: android.database.sqlite.SQLiteException: no such table: generalSettings (code 1): , while compiling: select * from generalSettings
错误。
下面是我的 sqlite 帮助程序类,用于创建数据库和错误日志。在
assert/Master.db
中,我们有表格 generalSettings
。但将其复制到设备后,该表丢失了。这种情况只发生在少数用户身上。我搜索了解决方案,但找不到确切的解决方案。团队请帮我解决这个问题。
代码:
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import android.content.Context;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
import android.util.Log;
public class InstallDB extends SQLiteOpenHelper {
Context ctx;
String DBNAME;
String DBPATH;
Modules modObj = new Modules();
public InstallDB(Context context, String name) {
super(context, name, null, 1);
this.ctx = context;
this.DBNAME = name;
this.DBPATH = this.ctx.getDatabasePath(DBNAME).getAbsolutePath();
Log.e("Path 1", DBPATH);
}
public void createDataBase() {
boolean dbExist = checkDataBase();
SQLiteDatabase db_Read = null;
if (!dbExist) {
synchronized (this) {
db_Read = this.getReadableDatabase();
Log.e("Path 2", this.getReadableDatabase().getPath());
db_Read.close();
copyDataBase();
Log.v("copyDataBase---", "Successfully");
}
// try {
// } catch (IOException e) {
// throw new Error("Error copying database");
// }
}
}
private boolean checkDataBase() {
SQLiteDatabase checkDB = null;
try {
String myPath = DBPATH;
checkDB = SQLiteDatabase.openDatabase(myPath, null,
SQLiteDatabase.OPEN_READWRITE);
} catch (Exception e) {
Log.i("SQLite Error", "database does't exist yet.");
}
if (checkDB != null) {
checkDB.close();
}
return checkDB != null ? true : false;
}
private void copyDataBase() {
try {
InputStream myInput = ctx.getAssets().open(DBNAME);
String outFileName = DBPATH;
OutputStream myOutput = new FileOutputStream(outFileName);
byte[] buffer = new byte[1024 * 3];
int length = 0;
while ((length = myInput.read(buffer)) > 0) {
myOutput.write(buffer, 0, length);
}
myOutput.flush();
myOutput.close();
myInput.close();
} catch (Exception e) {
Modules.stacTaceElement = e.getStackTrace();
StringWriter stackTrace1 = new StringWriter();
e.printStackTrace(new PrintWriter(stackTrace1));
System.err.println(stackTrace1);
Intent send = new Intent(Intent.ACTION_SENDTO);
String uriText;
uriText = "mailto:[email protected]"
+ "&subject=Error Report"
+ "&body="
+ stackTrace1.toString();
uriText = uriText.replace(" ", "%20");
Uri uri = Uri.parse(uriText);
send.setData(uri);
ctx.startActivity(Intent.createChooser(send, "Send mail..."));
// TODO: handle exception
}
}
@Override
public void onCreate(SQLiteDatabase db) {
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
错误日志:
java.lang.RuntimeException: Unable to start activity ComponentInfo{palmagent.FidelityAgent.Two/palmagent.FidelityAgent.Two.PassNew}: android.database.sqlite.SQLiteException: no such table: generalSettings (code 1): , while compiling: select * from generalSettings
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2209)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2269)
at android.app.ActivityThread.access$800(ActivityThread.java:139)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1210)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:136)
at android.app.ActivityThread.main(ActivityThread.java:5102)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:515)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
at dalvik.system.NativeStart.main(Native Method)
Caused by: android.database.sqlite.SQLiteException: no such table: generalSettings (code 1): , while compiling: select * from generalSettings
at android.database.sqlite.SQLiteConnection.nativePrepareStatement(Native Method)
at android.database.sqlite.SQLiteConnection.acquirePreparedStatement(SQLiteConnection.java:889)
at android.database.sqlite.SQLiteConnection.prepare(SQLiteConnection.java:500)
at android.database.sqlite.SQLiteSession.prepare(SQLiteSession.java:588)
at android.database.sqlite.SQLiteProgram.<init>(SQLiteProgram.java:58)
at android.database.sqlite.SQLiteQuery.<init>(SQLiteQuery.java:37)
at android.database.sqlite.SQLiteDirectCursorDriver.query(SQLiteDirectCursorDriver.java:44)
at android.database.sqlite.SQLiteDatabase.rawQueryWithFactory(SQLiteDatabase.java:1314)
at android.database.sqlite.SQLiteDatabase.rawQuery(SQLiteDatabase.java:1253)
at palmagent.FidelityAgent.Two.masterDatabase.selectquery(masterDatabase.java:59)
at palmagent.FidelityAgent.Two.Modules.checkDatabase(Modules.java:28825)
at palmagent.FidelityAgent.Two.PassNew$LoaduserDetails.onPreExecute(PassNew.java:140)
at android.os.AsyncTask.executeOnExecutor(AsyncTask.java:587)
at android.os.AsyncTask.execute(AsyncTask.java:535)
at palmagent.FidelityAgent.Two.PassNew.onCreate(PassNew.java:120)
at android.app.Activity.performCreate(Activity.java:5248)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1110)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2173)
... 11 more
问题是因为某些设备正在升级您的应用程序,因此
checkDataBase()
返回true
,因此您没有调用copyDataBase()
。因此,您使用的以前的数据库没有 generalSettings
表。
要解决这个问题,请尝试:
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if(newVersion>oldVersion)
copyDatabase();
}
并更新你的构造函数:
public InstallDB(Context context, String name) {
super(context, name, null, DB_VERSION);
// DB_VERSION is an int,update it every new build
this.ctx = context;
this.DBNAME = name;
this.DBPATH = this.ctx.getDatabasePath(DBNAME).getAbsolutePath();
Log.e("Path 1", DBPATH);
}
花了几个小时后我得到了这个解决方案:
1) 设置 > 应用程序管理器
2) 选择应用程序
3)清除数据
4) 卸载应用程序
现在从 Android Studio 运行应用程序
希望这能正常工作
出现此错误是因为您没有使用 DATABASE_VERSION
public class DatabaseHelper extends SQLiteOpenHelper {
private static SQLiteDatabase sqliteDb;
private static DatabaseHelper instance;
private static final int DATABASE_VERSION = 1;
每次在数据库中进行更改时增加版本只需将 DATABASE_VERSION 增加 +1..
另一种可能的解决方案是从 Android 模拟器中卸载应用程序,然后再次运行它。
如果您只想删除应用程序:
1.Start the emulator. 2.Open the Android settings app. 3.Select "Applications" (Called "Apps" on Android 4.0 or higher) 4.Select "Manage Applications" (Only on Android 3.2 or lower) 5.Select the application you want to uninstall. 6.Click "Uninstall"
假设如果您使用数据库版本 1 运行应用程序,那么如果您更改表结构或添加新表,则必须将数据库版本增加到 2,如果您对其进行更多更改,则必须将其进一步增加。
public class AppDatabase extends SQLiteOpenHelper {
// Database Name
private static final String DATABASE_NAME = "myDatabase";
// Database Version
private static final int DATABASE_VERSION = 1;
public AppDatabase(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
}
如果进行了任何更改,请增加此 DATABASE_VERSION 值。
即使您编写了几个表并升级了数据库,您的应用程序也会崩溃。您要做的就是为每个表创建数据库更改升级
DATABASE_VERSION
如果您的 DatabaseHelper 类很少(阅读本文),您必须将此方法添加到您的数据库助手中:
@Override
public void onOpen(SQLiteDatabase db) {
onCreate(db);
}
更新 DATABASE_VERSION 并卸载应用程序。现在运行该应用程序。
如果您使用 GreenDao 并收到此错误,请确保卸载该应用程序并重试。这解决了我的问题
这是一个升级异常。确保您以前的数据库中有该表。如果没有,请创建它。 PS:如果您是新开发此应用程序,请从模拟器或设备中卸载它并重新安装。但不建议这样做,因为数据不会丢失。
1.更改您的数据库版本 或者 首先卸载模拟器或手机中的应用程序并重新安装。 我想这样你的问题就会得到解决。
请像这样在主类中初始化复制数据库或数据库助手 数据库助手 = new Database(this); helper.execute(sqliteobj)
这是此问题的另一种解决方案,有时开发人员不知道列名称与其末尾之间没有空格(如 KEY_ADDRESS),这是错误的方法,在逗号和属性名称之间使用空格
尝试删除 getReadableDatabase
if (!dbExist) {
synchronized (this) {
db_Read = this.getReadableDatabase();
Log.e("Path 2", this.getReadableDatabase().getPath());
db_Read.close();
copyDataBase();
Log.v("copyDataBase---", "Successfully");
}
到
if (!dbExist) {
synchronized (this) {
//db_Read = this.getReadableDatabase();
// Log.e("Path 2", this.getReadableDatabase().getPath());
// db_Read.close();
copyDataBase();
Log.v("copyDataBase---", "Successfully");
}
当我为应用程序创建更新时,我遇到了同样的问题。 根据谷歌文档,仅在第一次安装应用程序时才调用 SQLiteOpenHelper 的 onCreate() 。 因此,如果你想添加一个表,你需要增加数据库版本并添加
onUpgrade() { your_table.create(database) }
@Override
public void onUpgrade(final SQLiteDatabase database,
final int oldVersion,
final int newVersion) {
YourTable.onCreate(database);
}
我的情况不同:
我正在使用
Room
的 createFromAsset()
在几个数据库文件之间切换,实现这一点需要首先删除数据库并再次重新创建它以加载其他数据库文件..
在删除过程中,我从数据库中观察到的
LiveData
会引发SQLiteException: no such table
,当然这是合乎逻辑的,因为LiveData
感知到底层数据发生了变化,并尝试获取新数据,并且发现桌子不见了
要解决这个问题:要么使用普通数据(无
LiveData
),要么停止观察LiveData
,并在数据库重新创建成功后再次重新观察。
注意:在不删除数据库文件的情况下,Room 继续使用旧数据库文件的缓存版本。
在我的例子中,我打开“设备文件资源管理器”选项卡并清除数据库文件。
然后我运行该应用程序。
它对我有用。
因为之前已经创建了数据库,所以当创建数据库附加建表时,建表失败。
你可以做的是单独创建表
public class MyDatabaseHelper extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "mydatabase.db";
private static final int DATABASE_VERSION = 1;
public MyDatabaseHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
// Create initial tables
db.execSQL("CREATE TABLE existing_table (id INTEGER PRIMARY KEY, name TEXT);");
// Add other initial table creation statements here
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// Handle database upgrade as needed
// For example, drop and recreate tables
}
// ##################### HERE ########################
public void createNewTable(SQLiteDatabase db) {
// Create a new table
db.execSQL("CREATE TABLE new_table (id INTEGER PRIMARY KEY, description TEXT);");
}
}
像这样创建表
MyDatabaseHelper dbHelper = new MyDatabaseHelper(this);
// Get writable database
SQLiteDatabase db = dbHelper.getWritableDatabase();
// Create new table
// #################### HERE ############################
dbHelper.createNewTable(db);
// Optionally, close the database connection
db.close();
就我而言,我更改了数据库名称及其对我的工作
尝试使用这个解决方案,这个对我有用:
选择应用程序
清除缓存
清除数据
卸载应用程序
然后从 Android Studio 运行应用程序