SQL 没有 table 但是 table 存在

SQL no such table But table exists

我使用 sqlite3 在 python 中创建了一个数据库文件。数据库包含 2 个表 ANSWERS,QUESTIONS。我想在我的 android 应用程序中使用该文件,我按照 this post 复制它而不是创建它。我复制了文件,实现了所示的方法,但我得到了 SQLiteException: no such table: QUESTIONS (code 1 SQLITE_ERROR): , while compiling: select * from QUESTIONS;。我在 sqlite 中对我的数据库进行了双重和三次检查,表在那里,名称是正确的。可能是什么地方的问题?我的助手 class 看起来像这样:

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();    

编辑:

What could be the issue at place?

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

您发布的 link 是一个旧的 link 并且有一个缺陷,它不适合更高版本的 Android。以后的版本默认使用WAL (Write-Ahead Logging) 将更改写入文件(后缀为 -wal 的数据库文件)。

如果数据库文件是通过 SQLiteDatabase openDatabaseMethod 使用 CREATE_IF_NECESSARY 创建的,然后被覆盖,则 WAL 文件用于创建的数据库而不是被覆盖的数据库 (使用 this.getReadableDatabase();在你的情况下这样做)。 SQLite 检测到这一点并认为数据库已损坏。 openDatabase 捕捉到这一点,并提供一个数据库,创建一个新的数据库,因此你最终得到一个只有 sqlite_master table.

的数据库

历史上所有这些都是用来规避数据库 folder/directory (data/data/databases) 不存在的,如果数据库文件不存在,正确的方法应该是创建文件夹(使用 getWritabledatabase 或 Readable 将创建数据库目录).

对于任何版本的 Android,正确且更有效的方法是检查数据库文件是否存在。如果是,则不要将资产和 return 复制到常规流程。

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

这是执行上述操作的片段,其中 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).");
      }
   }

这种仅文件方法效率更高,因为它不会增加打开和初始化数据库所需的处理量,只是为了随后将其覆盖和 re-opened。相反,它只是检查文件系统。