Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何在不重新创建表的情况下升级设备上预先填充的sqlite数据库?_Android_Sqlite_Sqliteopenhelper - Fatal编程技术网

Android 如何在不重新创建表的情况下升级设备上预先填充的sqlite数据库?

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

我的代码在下面。它可以正确读取我的资产文件夹中的sqlite数据库文件(我已经使用sqlite数据库浏览器创建了该文件)-将其移动到设备上的/data/data/packagename/databases/路径,然后我可以使用查询和光标来获取我的信息,效果非常好。代码如下:

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方法对我有多有用

做事的“正确”方式与你的出发方式大不相同。我假设您希望保留当前创建数据库的方法,而不是去那里,我将提供一个使用它的建议。向数据库中添加一个表,该表包含一行元数据,其中包括数据库版本(以及您喜欢的任何其他内容)。如果数据库文件已经存在,请打开它并检查版本。如果版本旧,请将其关闭并更换。

您有三个选项:

  • 使用onUpgrade()(首选)

  • 删除现有数据库并复制新数据库(不是一个好主意)

  • 复制现有数据库中的数据,删除现有数据库,复制新数据库,将旧数据库中的数据插入新数据库(在onUpgrade中升级新数据库架构时工作量过大)

  • 因此,为了回答您的问题,您可以在onUpgrade()中升级数据库,而无需重新创建任何表


    另一方面,如果您只是将新行添加到特定表中,则数据库模式没有更改,您可以在运行时插入新行。。。当然,不知道应用程序的用途这可能不是一个好主意,因为您很容易失去对“静态”数据库更改的跟踪。

    好的,如果我选择执行#1-onUpgrade,那么我想这就是我想知道的。由于我不会像大多数人那样用这种方法编写查询(插入、更改表等),那么我到底要做什么呢?你可以在upgrade()上做任何事情。其思想是管理数据库的用户版本。我建议您使用onUpgrade()运行一个简单的sql查询,该查询将在相应的表中插入新行。如果你给我行数据和表名,我可以给你一个例子,这真的很简单。另外,我还需要表的列名称。我理解,但我试图摆脱的是一堆硬编码的sql查询。例如,如果我需要添加100个新行怎么办?那会让我头疼的。如果下一次我不得不回来移除其中的25个,因为我决定我不需要那些特定的呢?然后我必须找到那25个,看看所有的insert语句。我在想,我只需要创建一个新的数据库文件,或者以某种方式删除(从资产中复制)创建的数据库-不确定这将如何工作-好吧,如果您的数据库是真正的“静态”,那么我认为选项#2适合您。我所说的“静态”是指没有最终用户对数据库中的数据进行任何更改。如果是这种情况,那么您需要做的就是去掉openDb()中的“If”语句方法,以便始终复制资产文件夹中的数据库。基本上,我只想使用SQLIte浏览器或通过终端更改我的数据库,并将更新后的数据库复制到资产文件夹中,并将这些更改复制到外部内存中,而无需每次更改时都写入/更改onUpgrade方法。不要硬接线路径。使用
    getDatabasePath()
    创建数据库文件的路径。