如何为Android创建SQL数据库?

3

嘿,我想知道如何为Android创建一个完整的数据库,而不是用户可编辑的数据库,并将其放在应用程序apk中。我需要使用Excel或Access然后将数据库添加到应用程序文件夹中吗?我在互联网上找到的都是如何使用应用程序本身添加数据的教程。那么,我该如何创建一个数据库呢?


可能是重复的问题:如何在Android应用程序中附带数据库? - Paul Woitaschek
我使用SQLiteManager FireFox插件。 - Phantômaxx
3个回答

1
如果我没记错的话,您只需将sqlite文件与数据库添加到应用程序资源中,并像这些一样使用DBHelper类,但要根据您的应用程序需求进行调整。
我个人使用这个Firefox扩展程序来创建和编辑sqlite文件。

0
你可以将现有的 SQLite 数据库放置到应用程序的 assets 文件夹中。如果在运行时访问此数据库,则可以使用以下代码打开数据库;
      SQLiteDatabase db = SQLiteDatabase.openDatabase("path-to-database", null, SQLiteDatabase.OPEN_READONLY);

目前我不知道是否可以直接从资源中打开db文件。否则,您可能需要将其复制到您的应用程序的内部数据库目录中:

private void copyDatabase(final Context context) {
  InputStream reader = null;
  try {
     reader = context.getAssets().open("asset-name");
     final File out = context.getDatabasePath("databasename");
     final OutputStream writer = new FileOutputStream(out);
     final byte[] buffer = new byte[1024 * 100];
     int bytesRead = reader.read(buffer);
     while (bytesRead > 0) {
        writer.write(buffer, 0, bytesRead);
        bytesRead = reader.read(buffer);
     }
     writer.close();
  } catch (IOException e) {
     Log.e(TAG, e.getMessage(), e);
  } finally {
     if (reader != null) {
        try {
           reader.close();
        } catch (IOException e) {
           Log.e(TAG, e.getMessage(), e);
        }
     }
  }
}

0

@Danny回答:

创建和更新数据库有两个选项。

一种是在外部创建数据库,然后将其放置在项目的assets文件夹中,然后从那里复制整个数据库。如果数据库有很多表和其他组件,则这样做会更快。通过在res/values/strings.xml文件中更改数据库版本号来触发升级。然后通过创建一个新的数据库,在assets文件夹中用新的数据库替换旧的数据库,在内部存储中将旧的数据库另存为另一个名称,将新的数据库从assets文件夹复制到内部存储中,将旧的数据库中的所有数据(之前重命名)转移到新的数据库中,最后删除旧的数据库来完成升级。您可以使用SQLite Manager FireFox插件执行创建SQL语句来最初创建数据库。

另一种选择是从SQL文件内部创建数据库。如果数据库只有几个表,则速度不如第一种方法快,但用户可能无法察觉到延迟。通过在res/values/strings.xml文件中更改数据库版本号来触发升级。然后通过处理升级SQL文件来完成升级。除非删除其容器(例如删除表),否则数据库中的数据将保持不变。

下面的示例演示了如何使用任一方法。

这是一个示例 create_database.sql 文件。它应该放置在项目的 assets 文件夹中,用于内部方法,或者复制到 SQLite Manager 的“执行 SQL”中,以创建外部方法的数据库。(注意:请注意 Android 所需的表的注释。)

--Android requires a table named 'android_metadata' with a 'locale' column
CREATE TABLE "android_metadata" ("locale" TEXT DEFAULT 'en_US');
INSERT INTO "android_metadata" VALUES ('en_US');

CREATE TABLE "kitchen_table";
CREATE TABLE "coffee_table";
CREATE TABLE "pool_table";
CREATE TABLE "dining_room_table";
CREATE TABLE "card_table"; 

这里是一个样例的 update_database.sql 文件。它应该被放置在项目的 assets 文件夹中作为内部方法使用,或者被复制到 SQLite Manager 的 "执行 SQL" 中用于创建外部方法的数据库。(注意:请注意,此示例中包含的 sql 解析器将忽略所有三种类型的 sql 注释。)

--CREATE TABLE "kitchen_table";  This is one type of comment in sql.  It is ignored by parseSql.
/*
 * CREATE TABLE "coffee_table"; This is a second type of comment in sql.  It is ignored by parseSql.
 */
{
CREATE TABLE "pool_table";  This is a third type of comment in sql.  It is ignored by parseSql.
}
/* CREATE TABLE "dining_room_table"; This is a second type of comment in sql.  It is ignored by parseSql. */
{ CREATE TABLE "card_table"; This is a third type of comment in sql.  It is ignored by parseSql. }

--DROP TABLE "picnic_table"; Uncomment this if picnic table was previously created and now is being replaced.
CREATE TABLE "picnic_table" ("plates" TEXT);
INSERT INTO "picnic_table" VALUES ('paper');

这是一个要添加到 /res/values/strings.xml 文件中的条目,用于数据库版本号。
<item type="string" name="databaseVersion" format="integer">1</item>

这里有一个访问数据库并使用它的活动。(注意:如果数据库代码使用了大量资源,您可能需要在单独的线程中运行它。)

    package android.example;

import android.app.Activity;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;

/**
 * @author Danny Remington - MacroSolve
 * 
 *         Activity for demonstrating how to use a sqlite database.
 */
public class Database extends Activity {
     /** Called when the activity is first created. */
     @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        DatabaseHelper myDbHelper;
        SQLiteDatabase myDb = null;

        myDbHelper = new DatabaseHelper(this);
        /*
         * Database must be initialized before it can be used. This will ensure
         * that the database exists and is the current version.
         */
         myDbHelper.initializeDataBase();

         try {
            // A reference to the database can be obtained after initialization.
            myDb = myDbHelper.getWritableDatabase();
            /*
             * Place code to use database here.
             */
         } catch (Exception ex) {
            ex.printStackTrace();
         } finally {
            try {
                myDbHelper.close();
            } catch (Exception ex) {
                ex.printStackTrace();
            } finally {
                myDb.close();
            }
        }

    }
}

下面是数据库帮助类,它可以在需要时创建或更新数据库。(注意:Android要求您创建一个继承自SQLiteOpenHelper的类才能使用Sqlite数据库。)

    package android.example;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

/**
 * @author Danny Remington - MacroSolve
 * 
 *         Helper class for sqlite database.
 */
public class DatabaseHelper extends SQLiteOpenHelper {

    /*
     * The Android's default system path of the application database in internal
     * storage. The package of the application is part of the path of the
     * directory.
     */
    private static String DB_DIR = "/data/data/android.example/databases/";
    private static String DB_NAME = "database.sqlite";
    private static String DB_PATH = DB_DIR + DB_NAME;
    private static String OLD_DB_PATH = DB_DIR + "old_" + DB_NAME;

    private final Context myContext;

    private boolean createDatabase = false;
    private boolean upgradeDatabase = false;

    /**
     * Constructor Takes and keeps a reference of the passed context in order to
     * access to the application assets and resources.
     * 
     * @param context
     */
    public DatabaseHelper(Context context) {
        super(context, DB_NAME, null, context.getResources().getInteger(
                R.string.databaseVersion));
        myContext = context;
        // Get the path of the database that is based on the context.
        DB_PATH = myContext.getDatabasePath(DB_NAME).getAbsolutePath();
    }

    /**
     * Upgrade the database in internal storage if it exists but is not current. 
     * Create a new empty database in internal storage if it does not exist.
     */
    public void initializeDataBase() {
        /*
         * Creates or updates the database in internal storage if it is needed
         * before opening the database. In all cases opening the database copies
         * the database in internal storage to the cache.
         */
        getWritableDatabase();

        if (createDatabase) {
            /*
             * If the database is created by the copy method, then the creation
             * code needs to go here. This method consists of copying the new
             * database from assets into internal storage and then caching it.
             */
            try {
                /*
                 * Write over the empty data that was created in internal
                 * storage with the one in assets and then cache it.
                 */
                copyDataBase();
            } catch (IOException e) {
                throw new Error("Error copying database");
            }
        } else if (upgradeDatabase) {
            /*
             * If the database is upgraded by the copy and reload method, then
             * the upgrade code needs to go here. This method consists of
             * renaming the old database in internal storage, create an empty
             * new database in internal storage, copying the database from
             * assets to the new database in internal storage, caching the new
             * database from internal storage, loading the data from the old
             * database into the new database in the cache and then deleting the
             * old database from internal storage.
             */
            try {
                FileHelper.copyFile(DB_PATH, OLD_DB_PATH);
                copyDataBase();
                SQLiteDatabase old_db = SQLiteDatabase.openDatabase(OLD_DB_PATH, null, SQLiteDatabase.OPEN_READWRITE);
                SQLiteDatabase new_db = SQLiteDatabase.openDatabase(DB_PATH,null, SQLiteDatabase.OPEN_READWRITE);
                /*
                 * Add code to load data into the new database from the old
                 * database and then delete the old database from internal
                 * storage after all data has been transferred.
                 */
            } catch (IOException e) {
                throw new Error("Error copying database");
            }
        }

    }

    /**
     * Copies your database from your local assets-folder to the just created
     * empty database in the system folder, from where it can be accessed and
     * handled. This is done by transfering bytestream.
     * */
    private void copyDataBase() throws IOException {
        /*
         * Close SQLiteOpenHelper so it will commit the created empty database
         * to internal storage.
         */
        close();

        /*
         * Open the database in the assets folder as the input stream.
         */
        InputStream

     myInput = myContext.getAssets().open(DB_NAME);

            /*
             * Open the empty db in interal storage as the output stream.
             */
            OutputStream myOutput = new FileOutputStream(DB_PATH);

            /*
             * Copy over the empty db in internal storage with the database in the
             * assets folder.
             */
            FileHelper.copyFile(myInput, myOutput);

            /*
             * Access the copied database so SQLiteHelper will cache it and mark it
             * as created.
             */
            getWritableDatabase().close();
        }

        /*
         * This is where the creation of tables and the initial population of the
         * tables should happen, if a database is being created from scratch instead
         * of being copied from the application package assets. Copying a database
         * from the application package assets to internal storage inside this
         * method will result in a corrupted database.
         * <P>
         * NOTE: This method is normally only called when a database has not already
         * been created. When the database has been copied, then this method is
         * called the first time a reference to the database is retrieved after the
         * database is copied since the database last cached by SQLiteOpenHelper is
         * different than the database in internal storage.
         */
        @Override
        public void onCreate(SQLiteDatabase db) {
            /*
             * Signal that a new database needs to be copied. The copy process must
             * be performed after the database in the cache has been closed causing
             * it to be committed to internal storage. Otherwise the database in
             * internal storage will not have the same creation timestamp as the one
             * in the cache causing the database in internal storage to be marked as
             * corrupted.
             */
            createDatabase = true;

            /*
             * This will create by reading a sql file and executing the commands in
             * it.
             */
                // try {
                // InputStream is = myContext.getResources().getAssets().open(
                // "create_database.sql");
                //
                // String[] statements = FileHelper.parseSqlFile(is);
                //
                // for (String statement : statements) {
                // db.execSQL(statement);
                // }
                // } catch (Exception ex) {
                // ex.printStackTrace();
                // }
        }

        /**
         * Called only if version number was changed and the database has already
         * been created. Copying a database from the application package assets to
         * the internal data system inside this method will result in a corrupted
         * database in the internal data system.
         */
        @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            /*
             * Signal that the database needs to be upgraded for the copy method of
             * creation. The copy process must be performed after the database has
             * been opened or the database will be corrupted.
             */
            upgradeDatabase = true;

            /*
             * Code to update the database via execution of sql statements goes
             * here.
             */

            /*
             * This will upgrade by reading a sql file and executing the commands in
             * it.
             */
            // try {
            // InputStream is = myContext.getResources().getAssets().open(
            // "upgrade_database.sql");
            //
            // String[] statements = FileHelper.parseSqlFile(is);
            //
            // for (String statement : statements) {
            // db.execSQL(statement);
            // }
            // } catch (Exception ex) {
            // ex.printStackTrace();
            // }
        }

        /**
         * Called everytime the database is opened by getReadableDatabase or
         * getWritableDatabase. This is called after onCreate or onUpgrade is
         * called.
         */
        @Override
        public void onOpen(SQLiteDatabase db) {
            super.onOpen(db);
        }

        /*
         * Add your public helper methods to access and get content from the
         * database. You could return cursors by doing
         * "return myDataBase.query(....)" so it'd be easy to you to create adapters
         * for your views.
         */

    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接