Android 如何在不重新创建表的情况下升级设备上预先填充的sqlite数据库?
我的代码在下面。它可以正确读取我的资产文件夹中的sqlite数据库文件(我已经使用sqlite数据库浏览器创建了该文件)-将其移动到设备上的/data/data/packagename/databases/路径,然后我可以使用查询和光标来获取我的信息,效果非常好。代码如下:Android 如何在不重新创建表的情况下升级设备上预先填充的sqlite数据库?,android,sqlite,sqliteopenhelper,Android,Sqlite,Sqliteopenhelper,我的代码在下面。它可以正确读取我的资产文件夹中的sqlite数据库文件(我已经使用sqlite数据库浏览器创建了该文件)-将其移动到设备上的/data/data/packagename/databases/路径,然后我可以使用查询和光标来获取我的信息,效果非常好。代码如下: public class DatabaseHelper extends SQLiteOpenHelper { private Context myDbContext; private static String dbNam
public class DatabaseHelper extends SQLiteOpenHelper {
private Context myDbContext;
private static String dbName = "restaurant.db";
private static String outfilePath = "/data/data/dev.mypackage.com/databases/";
private static String path = outfilePath + dbName;
private static SQLiteDatabase db;
public DatabaseHelper(Context context){
super(context, dbName, null, 2);
this.myDbContext = context;
db = openDb();
String s = "select * from menu";
Cursor c = db.rawQuery(s, null);
Log.e("DB Constructor Row count", String.valueOf(c.getCount()).toString());
while(c.moveToNext()){
Log.e("DB Constructor", c.getString(c.getColumnIndex("category")));
Log.e("DB Constructor", c.getString(c.getColumnIndex("menuItem_id")));
Log.e("DB Constructor", c.getString(c.getColumnIndex("title")));
Log.e("DB Constructor", c.getString(c.getColumnIndex("desc")));
Log.e("DB Constructor", c.getString(c.getColumnIndex("price")));
Log.e("DB Constructor", c.getString(c.getColumnIndex("icon")));
}
c.deactivate();
c.close();
}
private void copyDataBase(File dbFile) throws IOException {
try{
InputStream dbStream = myDbContext.getAssets().open(dbName);
OutputStream newDbFile = new FileOutputStream(outfilePath + dbName);
byte[] buffer = new byte[1024];
int length;
while((length = dbStream.read(buffer)) > 0){
newDbFile.write(buffer);
}
newDbFile.flush();
newDbFile.close();
dbStream.close();
}
catch(IOException e){
throw new IOException("trying to copy the database - ERROR: " + e.getMessage());
}
}
private SQLiteDatabase openDb() throws SQLiteException{
File dbFile = myDbContext.getDatabasePath(dbName);
if(!dbFile.exists()){
Log.e("openDb", "file does not exist");
try {
copyDataBase(dbFile);
} catch (IOException e) {
throw new RuntimeException("Error creating source database", e);
}
}
return SQLiteDatabase.openDatabase(path, null, SQLiteDatabase.OPEN_READONLY);
}
public void loadRestaurantInfo(){
}
@Override
public void onCreate(SQLiteDatabase db){
// TODO Auto-generated method stub
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
现在,我必须返回并使用SQLite浏览器将一行信息添加到其中一个表中(在assets文件夹的数据库中),但这并没有反映在我的游标输出中-我理解为什么会发生这种情况-因为如果(!dbFile.exists())失败,那么就不会进行复制。所以我的问题是-我需要添加什么代码来实现这一点?我从来没有用代码创建过表,所以我不知道onUpgrade方法对我有多有用 做事的“正确”方式与你的出发方式大不相同。我假设您希望保留当前创建数据库的方法,而不是去那里,我将提供一个使用它的建议。向数据库中添加一个表,该表包含一行元数据,其中包括数据库版本(以及您喜欢的任何其他内容)。如果数据库文件已经存在,请打开它并检查版本。如果版本旧,请将其关闭并更换。您有三个选项:
另一方面,如果您只是将新行添加到特定表中,则数据库模式没有更改,您可以在运行时插入新行。。。当然,不知道应用程序的用途这可能不是一个好主意,因为您很容易失去对“静态”数据库更改的跟踪。好的,如果我选择执行#1-onUpgrade,那么我想这就是我想知道的。由于我不会像大多数人那样用这种方法编写查询(插入、更改表等),那么我到底要做什么呢?你可以在upgrade()上做任何事情。其思想是管理数据库的用户版本。我建议您使用onUpgrade()运行一个简单的sql查询,该查询将在相应的表中插入新行。如果你给我行数据和表名,我可以给你一个例子,这真的很简单。另外,我还需要表的列名称。我理解,但我试图摆脱的是一堆硬编码的sql查询。例如,如果我需要添加100个新行怎么办?那会让我头疼的。如果下一次我不得不回来移除其中的25个,因为我决定我不需要那些特定的呢?然后我必须找到那25个,看看所有的insert语句。我在想,我只需要创建一个新的数据库文件,或者以某种方式删除(从资产中复制)创建的数据库-不确定这将如何工作-好吧,如果您的数据库是真正的“静态”,那么我认为选项#2适合您。我所说的“静态”是指没有最终用户对数据库中的数据进行任何更改。如果是这种情况,那么您需要做的就是去掉openDb()中的“If”语句方法,以便始终复制资产文件夹中的数据库。基本上,我只想使用SQLIte浏览器或通过终端更改我的数据库,并将更新后的数据库复制到资产文件夹中,并将这些更改复制到外部内存中,而无需每次更改时都写入/更改onUpgrade方法。不要硬接线路径。使用
getDatabasePath()
创建数据库文件的路径。