[android] Android SQLite 데이터베이스에 테이블이 있는지 어떻게 확인합니까?

데이터베이스에 이미 레코드가 있는지 확인하고 그렇지 않은 경우 일부를 처리하고 결국 삽입하고 데이터가 존재하는 경우 데이터베이스에서 데이터를 읽어야하는 Android 앱이 있습니다. SQLiteOpenHelper의 하위 클래스를 사용하여 SQLiteDatabase의 재기록 가능한 인스턴스를 만들고 가져오고 있는데, 테이블이 아직 존재하지 않는 경우 자동으로 테이블 생성을 처리했다고 생각했습니다 (이 작업을 수행하는 코드는 onCreate (… ) 방법).

그러나 테이블이 아직 존재하지 않고 내가 가지고있는 SQLiteDatabase 객체에 대해 실행 된 첫 번째 메서드가 query (…)에 대한 호출 인 경우 내 logcat에 “I / Database (26434) : sqlite returns : error code = 1, msg = no such table : appdata “이며, 확실히 appdata 테이블이 생성되지 않습니다.

이유에 대한 아이디어가 있습니까?

나는 테이블이 존재하는지 테스트하는 방법을 찾고 있습니다 (그렇지 않으면 데이터가 확실히 거기에 없기 때문에 테이블을 만드는 것처럼 보일 때까지 읽을 필요가 없기 때문입니다. 적절하게) 또는 query (…)에 대한 첫 번째 호출에 맞춰 생성되고 비어 있는지 확인하는 방법

편집

이것은 아래 두 가지 답변 후에 게시되었습니다

. 문제를 발견했을 수 있다고 생각합니다. 나는 어떤 이유로 든 동일한 데이터베이스 파일에 액세스하더라도 각 테이블에 대해 다른 SQLiteOpenHelper를 만들어야한다고 결정했습니다. 하나의 OpenHelper 만 사용하도록 해당 코드를 리팩토링하고 onCreate 안에 두 테이블을 모두 만드는 것이 더 잘 작동 할 수 있다고 생각합니다.



답변

이걸로 해봐:

public boolean isTableExists(String tableName, boolean openDb) {
    if(openDb) {
        if(mDatabase == null || !mDatabase.isOpen()) {
            mDatabase = getReadableDatabase();
        }

        if(!mDatabase.isReadOnly()) {
            mDatabase.close();
            mDatabase = getReadableDatabase();
        }
    }

    String query = "select DISTINCT tbl_name from sqlite_master where tbl_name = '"+tableName+"'";
    try (Cursor cursor = mDatabase.rawQuery(query, null)) {
        if(cursor!=null) {
            if(cursor.getCount()>0) {
                return true;
            }
        }
        return false;
    }
}


답변

Android SQLite API에 대해 아무것도 모르지만 SQL에서 직접 대화 할 수 있다면 다음과 같이 할 수 있습니다.

create table if not exists mytable (col1 type, col2 type);

이렇게하면 테이블이 항상 생성되고 이미 존재하는 경우 오류가 발생하지 않습니다.


답변

이 질문에 대한 좋은 답변이 이미 많이 있지만 더 간단하다고 생각되는 또 다른 해결책을 찾았습니다. try 블록과 다음 catch로 쿼리를 묶습니다.

catch (SQLiteException e){
    if (e.getMessage().contains("no such table")){
            Log.e(TAG, "Creating table " + TABLE_NAME + "because it doesn't exist!" );
            // create table
            // re-run query, etc.
    }
}

그것은 나를 위해 일했습니다!


답변

이것이 내가 한 일입니다.

/* open database, if doesn't exist, create it */
SQLiteDatabase mDatabase = openOrCreateDatabase("exampleDb.db", SQLiteDatabase.CREATE_IF_NECESSARY,null);

Cursor c = null;
boolean tableExists = false;
/* get cursor on it */
try
{
    c = mDatabase.query("tbl_example", null,
        null, null, null, null, null);
        tableExists = true;
}
catch (Exception e) {
    /* fail */
    Log.d(TAG, tblNameIn+" doesn't exist :(((");
}

return tableExists;


답변

네, 내 편집의 이론이 옳았습니다. onCreate 메서드가 실행되지 않는 문제는 SQLiteOpenHelper개체가 데이터베이스를 참조해야하고 각 테이블에 대해 별도의 데이터베이스가 없어야 한다는 사실이었습니다 . 두 테이블을 하나로 묶어 SQLiteOpenHelper문제가 해결되었습니다.


답변

메서드 를 확장 SQLiteOpenHelper하고 구현 하는 클래스를 만들었다 고 언급했습니다 onCreate. 해당 클래스로 모든 데이터베이스 획득 호출을 수행하고 있는지 확인하고 있습니까? 를 통해서만 SQLiteDatabase객체를 가져와야 SQLiteOpenHelper#getWritableDatabase하며 getReadableDatabase그렇지 않으면 onCreate필요할 때 메서드가 호출되지 않습니다. 이미 그렇게하고 있다면 th SQLiteOpenHelper#onUpgrade메소드가 대신 호출 되는지 확인하십시오 . 그렇다면 데이터베이스 버전 번호가 어느 시점에서 변경되었지만 테이블이 제대로 생성되지 않은 것입니다.

제쳐두고, 데이터베이스에 대한 모든 연결이 닫혔는지 확인하고 호출 Context#deleteDatabase한 다음를 사용하여 SQLiteOpenHelper새 db 개체를 제공 하여 데이터베이스를 강제로 다시 만들 수 있습니다.


답변

 // @param db, readable database from SQLiteOpenHelper

 public boolean doesTableExist(SQLiteDatabase db, String tableName) {
        Cursor cursor = db.rawQuery("select DISTINCT tbl_name from sqlite_master where tbl_name = '" + tableName + "'", null);

    if (cursor != null) {
        if (cursor.getCount() > 0) {
            cursor.close();
            return true;
        }
        cursor.close();
    }
    return false;
}
  • sqlite는 데이터베이스의 모든 테이블과 인덱스에 대한 정보를 포함하는 sqlite_master 테이블을 유지합니다.
  • 그래서 여기서 우리는 단순히 SELECT 명령을 실행하고 있으며 테이블이 존재하면 커서가 1 인 커서를 얻습니다.