如何使用我自己的sqlite数据库?

时间:2010-03-05 14:33:45

标签: database android sqlite

我将数据库字段放在“assets”文件夹中。并使用此blog中的代码将数据库复制到“/ data / data / my_packname / databases /”,(此复制代码我在运行此应用程序时在onCreate()方法中运行它)然后使用select * from ...来获取数据。但它给了我一个例外:没有这样的表。

有人告诉我,如果我试图在SQLiteOpenHelper的onCreate()中复制文件,那就太晚了。因此复制文件代码无法复制整个文件。

所以我需要先用adb或ddms拉数据库吗?

那么,任何人都可以教我如何使用自己的数据库? 你能告诉我这个设置吗?

7 个答案:

答案 0 :(得分:12)

我已经使用了该博文中的说明,发现它们在正确的轨道上通过不必要地扩展SQLiteOpenHelper来严重地使问题复杂化。我做了以下更好的运气:

  1. 创建一个实用程序类,通过将静态数据库从资产复制到正确的目录中来创建静态数据库,但不会因为SQLiteOpenHelper格式而陷入困境。

  2. 使用相同的实用程序类,使用SQLiteDatabase.openDatabase()

  3. 打开数据库

    编辑:这是我创建的这个实用程序类的一个版本;它不是很完整,但你会得到漂移。

    public class DbUtils {
        private static final String DB_PATH = "/data/data/com.mypackage.myapp/databases/";
        private static final String DB_NAME = "my.db";
    
        public static void createDatabaseIfNotExists(Context context) throws IOException {
            boolean createDb = false;
    
            File dbDir = new File(DB_PATH);
            File dbFile = new File(DB_PATH + DB_NAME);
            if (!dbDir.exists()) {
                dbDir.mkdir();
                createDb = true;
            }
            else if (!dbFile.exists()) {
                createDb = true;
            }
            else {
                // Check that we have the latest version of the db
                boolean doUpgrade = false;
    
                // Insert your own logic here on whether to upgrade the db; I personally
                // just store the db version # in a text file, but you can do whatever
                // you want.  I've tried MD5 hashing the db before, but that takes a while.
    
                // If we are doing an upgrade, basically we just delete the db then
                // flip the switch to create a new one
                if (doUpgrade) {
                    dbFile.delete();
                    createDb = true;
                }
            }
    
            if (createDb) {
                // Open your local db as the input stream
                InputStream myInput = context.getAssets().open(DB_NAME);
    
                // Open the empty db as the output stream
                OutputStream myOutput = new FileOutputStream(dbFile);
    
                // transfer bytes from the inputfile to the outputfile
                byte[] buffer = new byte[1024];
                int length;
                while ((length = myInput.read(buffer)) > 0) {
                    myOutput.write(buffer, 0, length);
                }
    
                // Close the streams
                myOutput.flush();
                myOutput.close();
                myInput.close();
            }
        }
    
        public static SQLiteDatabase getStaticDb() {
            return SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY);
        }
    }
    

答案 1 :(得分:1)

复制数据库后,应尝试关闭并重新打开SQLiteDatabase对象,然后再对其执行任何查询。从输入流中复制数据库时遇到了类似的问题,这就是解决它的问题。

答案 2 :(得分:0)

这是我的版本来自“Silvio Donnini”代码:), 现在您可以轻松更新数据库了。

private static final String DB_PATH = "/data/data/pakagename/databases/";
private static final String DB_NAME = "databaseName";     
private static SQLiteDatabase db;

public static void createDatabaseIfNotExists(Context context,int version) throws IOException {
    boolean createDb = false;

    File dbDir = new File(DB_PATH);
    File dbFile = new File(DB_PATH + DB_NAME);
    if (!dbDir.exists()) {
        dbDir.mkdir();
        createDb = true;
    }
    else if (!dbFile.exists()) {
        createDb = true;
    }
    else {
        // Check that we have the latest version of the db       
         db = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY);

        if (db.getVersion() != version) {
            dbFile.delete();
            createDb = true;
        }

    }

    if (createDb) {

        // Open your local db as the input stream
        InputStream myInput = context.getResources().openRawResource(R.raw.database);

        // Open the empty db as the output stream
        OutputStream myOutput = new FileOutputStream(dbFile);

        // transfer bytes from the inputfile to the outputfile
        byte[] buffer = new byte[1024];
        int length;
        while ((length = myInput.read(buffer)) > 0) {
            myOutput.write(buffer, 0, length);
        }

        // Close the streams
        myOutput.flush();
        myOutput.close();
        myInput.close();
        SQLiteDatabase dbwrite = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READWRITE);
        dbwrite.setVersion(version);
        dbwrite.close();
        if (db != null)
            db = SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY);

    }
}

public static SQLiteDatabase getStaticDb() {
     if (db != null)
         return db;

    return SQLiteDatabase.openDatabase(DB_PATH + DB_NAME, null, SQLiteDatabase.OPEN_READONLY);
}

答案 3 :(得分:0)

我知道这是一个老问题,但在所有回复的帮助下,我失去了很多时间来搞清楚。


问题是设备将数据库存储在其data / data /.../ databases文件夹中。所以,当你改变数据库(名称,添加android元数据表,大小......)时,由于存储的数据库和检查现有数据库的方法,它不会有任何区别。


要获取最新的数据库,在更改它之后,必须运行该程序而不检查现有的数据库(例如,而不是dbExist = checkDataBase();使其只是假)。

dbExist = checkDataBase();

更改为:

dbExists = false;

拿起“新”数据库后,您可以返回检查现有数据库。

希望它对某人有帮助, 迪娜

答案 4 :(得分:0)

我知道这是一篇旧帖子,但是对于那些在Google或Bing搜索后仍然在这里的人来说,这是所述问题的解决方案:

在createDataBase()中有以下检查;

this.getReadableDatabase();

这将检查是否已存在具有所提供名称的数据库,如果没有,则创建一个空数据库,以便可以使用assets文件夹中的数据库覆盖该数据库。在较新的设备上,这可以完美地工作,但有一些设备无法正常工作。主要是旧设备。我不确切知道为什么,但似乎getReadableDatabase()函数不仅获取数据库而且还打开它。如果您随后从assets文件夹复制数据库,它仍然具有指向空数据库的指针,您将获得表不存在错误。

因此,为了使其适用于所有设备,您应该将其修改为以下几行:

SQLiteDatabase db = this.getReadableDatabase();
if (db.isOpen()){
    db.close();
}

即使数据库在支票中被打开,它也会在此后关闭,它不会给您带来任何麻烦。

答案 5 :(得分:0)

冷静下来,经过长时间的研究终于找到了“没有这样的表”错误的愚蠢错误

检查Assets文件夹中的数据库名称,如果它类似于“DATABASE_NAME.EXTENSION”,然后在Helper类中使用扩展名来解决我的问题。

就像资产数据库中的名称是login.sqlite或login.db一样。将DB_NAME = login.sqlite完全放在extention中。  this tutorial现在效果很好。

答案 6 :(得分:-1)

从您发布的文章创建数据库的方式与在android示例中完成的方式略有不同(我不想说它是好还是坏)。

我已经学会了如何使用SDKs NotePad sample

中的数据库

这是一个很好的例子,因为它涵盖了数据库创建主题和通过ContentProvider进行数据库访问(它实际上是从db获取数据的唯一好方法,否则当尝试从许多地方同时获取数据时你会遇到问题你的代码)。

你应该注意到SQLiteOpenHelper非常强大,如果你能正确使用它,“它会帮助你”。例如,它存储当前数据库版本(不是sqlite版本,但是您使用数据库模式版本编号),当您使用新数据库结构创建新应用程序版本时,可以将当前模式更新为onUpdate中的新版本。