SQL没有这样的表,但是存在

发布于 2025-01-22 15:12:46 字数 3482 浏览 2 评论 0原文

我使用sqlite3在python中制作了一个数据库文件。数据库保留2个表答案,问题。我想在我的android应用中使用该文件,然后遵循 this 发布以复制它而不是创建它。我复制了该文件,如图所示实现了这些方法,但是我得到了一个sqliteException:no这样表:问题(代码1 sqlite_error):,在编译时:从问题中选择 * *。我在sqlite中进行了加倍,并在sqlite中进行了三次研究,表格在那里,名称是正确的。到处有什么问题?我的助手类看起来像这样:

public class DatabaseHelper extends SQLiteOpenHelper {
    private static String TAG = "DataBaseHelper"; // Tag just for the LogCat window
    private static String DB_NAME ="quiz.db"; // Database name
    private static int DB_VERSION = 1; // Database version
    private final File DB_FILE;
    private SQLiteDatabase mDataBase;
    private final Context mContext;
    public DatabaseHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
        DB_FILE = context.getDatabasePath(DB_NAME);
        this.mContext = context;
    }
    public void createDataBase() throws IOException {
        // If the database does not exist, copy it from the assets.
        boolean mDataBaseExist = checkDataBase();
        if (!mDataBaseExist) {
            this.getReadableDatabase();
            this.close();
            try {
                // Copy the database from assests
                copyDataBase();
                Log.e(TAG, "createDatabase database created");
            } catch (IOException mIOException) {
                throw new Error("ErrorCopyingDataBase");
            }
        }
    }
    // Check that the database file exists in databases folder
    private boolean checkDataBase() {
        return DB_FILE.exists();
    }
    // Copy the database from assets
    private void copyDataBase() throws IOException {
        InputStream mInput = mContext.getAssets().open(DB_NAME);
        OutputStream mOutput = new FileOutputStream(DB_FILE);
        byte[] mBuffer = new byte[1024];
        int mLength;
        while ((mLength = mInput.read(mBuffer)) > 0) {
            mOutput.write(mBuffer, 0, mLength);
        }
        mOutput.flush();
        mOutput.close();
        mInput.close();
    }
    // Open the database, so we can query it
    public boolean openDataBase() throws SQLException {
        mDataBase = SQLiteDatabase.openDatabase(String.valueOf(DB_FILE), null, SQLiteDatabase.CREATE_IF_NECESSARY);
        return mDataBase != null;
    }
    @Override
    public synchronized void close() {
        if(mDataBase != null) {
            mDataBase.close();
        }
        super.close();
    }
    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {}
    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {}
    public void testQuery() {
        mDataBase.rawQuery("select * from QUESTIONS;",null);
    }
}

我这样称呼它:

    helper = new DatabaseHelper(this);
    try {
        helper.createDataBase();
    } catch (IOException e) {
        e.printStackTrace();
    }
    try{
        helper.openDataBase();
    }catch (SQLException e){
        e.printStackTrace();
    }
    helper.testQuery();    

edit:

  • app/src/src/src/assets/quiz.db .db文件我物理上的路径复制到项目
  • data/data/com.rocket.src/databases此路径包含quiz.db quiz.db-journalquiz.dbquiz.db

I made a database file in python using sqlite3. The database holds 2 tables ANSWERS,QUESTIONS. I want to use that file in my android app and i followed this post to copy it instead of creating it. I copied the file,implemented the methods as shown,but I get an SQLiteException: no such table: QUESTIONS (code 1 SQLITE_ERROR): , while compiling: select * from QUESTIONS;. I double and triplechecked my database in sqlite,the tables are there,the names are correct. What could be the issue at place? My helper class looks like this:

public class DatabaseHelper extends SQLiteOpenHelper {
    private static String TAG = "DataBaseHelper"; // Tag just for the LogCat window
    private static String DB_NAME ="quiz.db"; // Database name
    private static int DB_VERSION = 1; // Database version
    private final File DB_FILE;
    private SQLiteDatabase mDataBase;
    private final Context mContext;
    public DatabaseHelper(Context context) {
        super(context, DB_NAME, null, DB_VERSION);
        DB_FILE = context.getDatabasePath(DB_NAME);
        this.mContext = context;
    }
    public void createDataBase() throws IOException {
        // If the database does not exist, copy it from the assets.
        boolean mDataBaseExist = checkDataBase();
        if (!mDataBaseExist) {
            this.getReadableDatabase();
            this.close();
            try {
                // Copy the database from assests
                copyDataBase();
                Log.e(TAG, "createDatabase database created");
            } catch (IOException mIOException) {
                throw new Error("ErrorCopyingDataBase");
            }
        }
    }
    // Check that the database file exists in databases folder
    private boolean checkDataBase() {
        return DB_FILE.exists();
    }
    // Copy the database from assets
    private void copyDataBase() throws IOException {
        InputStream mInput = mContext.getAssets().open(DB_NAME);
        OutputStream mOutput = new FileOutputStream(DB_FILE);
        byte[] mBuffer = new byte[1024];
        int mLength;
        while ((mLength = mInput.read(mBuffer)) > 0) {
            mOutput.write(mBuffer, 0, mLength);
        }
        mOutput.flush();
        mOutput.close();
        mInput.close();
    }
    // Open the database, so we can query it
    public boolean openDataBase() throws SQLException {
        mDataBase = SQLiteDatabase.openDatabase(String.valueOf(DB_FILE), null, SQLiteDatabase.CREATE_IF_NECESSARY);
        return mDataBase != null;
    }
    @Override
    public synchronized void close() {
        if(mDataBase != null) {
            mDataBase.close();
        }
        super.close();
    }
    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {}
    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {}
    public void testQuery() {
        mDataBase.rawQuery("select * from QUESTIONS;",null);
    }
}

And I call it like this:

    helper = new DatabaseHelper(this);
    try {
        helper.createDataBase();
    } catch (IOException e) {
        e.printStackTrace();
    }
    try{
        helper.openDataBase();
    }catch (SQLException e){
        e.printStackTrace();
    }
    helper.testQuery();    

EDIT:

  • app/src/main/assets/quiz.db The path from the .db file I physically copied to the project
  • data/data/com.rocket.src/databases This path contains quiz.db quiz.db-journal and quiz.dbquiz.db

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

情泪▽动烟 2025-01-29 15:12:46

到处有什么问题?

这现在可以很好地工作,老实说,我无法分辨发生了什么。

您发布的链接是一个旧的链接并且有缺陷,它不能满足以后版本的Android。以后的版本默认用于使用 wal w rite- rite- a head l ogging),其中更改写入文件(数据库文件以-WAL为后缀)。

如果数据库文件是通过sqlitedatabase opendatabasemethod创建的,则使用create_if_neusctary创建数据库文件,然后覆盖WAL文件是为创建数据库而不是oftritten oftritten数据库(使用this.getReadAbledabledatabase()使用this.getReadAbledatabase()您的情况)。 SQLITE检测到这一点,并将数据库视为损坏。 OpenDatabase捕获了这一点,并提供一个数据库,可以创建一个新的数据库,因此您最终获得了仅具有SQLITE_MASTER表的数据库。

以上所有内容在历史上都用于规避数据库文件夹/目录(数据/数据/数据库),如果正确的方法应该是在数据库文件不存在的情况下创建文件夹(使用GetWritabledabledatabase或可读性将创建数据库目录)。

对于任何版本的Android,正确,更有效的方法是检查数据库文件是否存在。如果确实这样做,则不会复制资产并返回通常的过程。

否则(如果数据库文件不存在),请获取父(数据库文件夹),请检查是否存在并且如果不存在,则将创建目录。然后可以从资产复制数据库文件。

这是执行以上db_name是数据库文件的名称的上述片段: -

   private void getDatabase(Context context) {
      File dbFile = new File(context.getDatabasePath((DB_NAME)).getPath());
      if (dbFile.exists()) return; // Database found so all done
      // Otherwise ensure that the database directory exists (does not by default until later versions)
      if (!dbFile.getParentFile().exists()) {
         dbFile.getParentFile().mkdirs();
      }
      if (!copyDataBase()) {
         throw new RuntimeException("Unable to copy database from the asset (check the stack-trace).");
      }
   }

此文件仅能进行更有效 - 开放。相反,它只会检查文件系统。

What could be the issue at place?

This works perfectly now,i honestly can't tell what happened.

The link you posted is an old link and has a flaw, it does not cater for later versions of Android. Later versions default to using WAL (Write-Ahead Logging) where changes are written to a file (database file suffixed with -wal).

If the database file is created via the SQLiteDatabase openDatabaseMethod with CREATE_IF_NECESSARY and then overwritten the WAL file is for the created database NOT the overwritten database (the use of this.getReadableDatabase(); does this in your case). SQLite detects this and considers the database as corrupt. The openDatabase catches this and, to provide a database, creates a new database and hence you end up with a database that only has the sqlite_master table.

All of the above was historically used to circumvent the databases folder/directory (data/data/databases) not existing, when the correct method should have been to create the folder if the database file doesn't exist (using getWritabledatabase or Readable will create the databases directory).

The correct and more efficient way, for any version of Android is to check if the database file exists. If it does then don't copy the asset and return to the usual process.

Otherwise (if the database file does not exist), then get the parent (the databases folder), check if that exists and if not then make the directory. The database file can then be copied from the asset.

Here's a snippet that does the above where DB_NAME is the name of the database file :-

   private void getDatabase(Context context) {
      File dbFile = new File(context.getDatabasePath((DB_NAME)).getPath());
      if (dbFile.exists()) return; // Database found so all done
      // Otherwise ensure that the database directory exists (does not by default until later versions)
      if (!dbFile.getParentFile().exists()) {
         dbFile.getParentFile().mkdirs();
      }
      if (!copyDataBase()) {
         throw new RuntimeException("Unable to copy database from the asset (check the stack-trace).");
      }
   }

This file only approach is more efficient as it does not incur the increased processing required to open and initialise a database, just for it to then be overwritten and re-opened. Instead it just checks the file system.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文