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


87

데이터베이스에 이미 레코드가 있는지 확인하고 그렇지 않은 경우 일부를 처리하고 결국 삽입하고 데이터가 존재하는 경우 데이터베이스에서 데이터를 읽어야하는 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 안에 두 테이블을 모두 만드는 것이 더 잘 작동 할 수 있다고 생각합니다.

답변:


127

이걸로 해봐:

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;
    }
}

감사합니다. 잘 작동합니다. +1
Gray

11
잊지 마세요cursor.close();
styler1972

1
알 수없는 이유로 테이블 이름은 대소 문자를 구분합니다. 차라리 사용select * from sqlite_master where UPPER(name) = 'ROUTES'.
Thupten

4
좋은 대답이지만 고통스러운 문법! 반드시 'isTableExisting ()'이라고해야합니다.
크리스 헤이 튼

1
이것은 나를 위해 일했지만 try / catch에서 쿼리를 래핑해야했습니다. 그렇지 않으면 테이블이 존재하지 않을 때 앱이 충돌합니다.
Braden Holt

52

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

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

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


이것이 SQLiteOpenHelper 클래스 내의 onCreate 메서드에서 테이블을 만드는 방법입니다. Android에서는 앱이 데이터베이스를 자동으로 업데이트 할 수 있고 일반적으로 분명히 더 효율적이므로 해당 클래스가 테이블을 생성하도록하는 것이 좋습니다. 불행하게도, 많은 당신 :( 시간에 달렸다을받지 쓴 것과 같은 그 코드 블록이 실행하는 코드
camperdave

이것은 훌륭하게 작동하며 색인에서도 작동합니다. 예 : "존재하지 않는 경우 색인 생성 [...]".
Eric Fortier 2013

5
이것은 실제로 질문에 대한 최상의 대답입니다.
The Original Android

1
하지만 문제는 하나를 만들 요구하지 않습니다
10101010

12

이 질문에 대한 좋은 답변이 이미 많이 있지만 더 간단하다고 생각되는 또 다른 해결책을 찾았습니다. 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.
    }
}

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


1
if () 블록 안에 Log 문을 넣는 것이 낫지 않습니까? SQLiteException이 "해당 테이블 없음"이외의 다른 이유로 인해 발생하면 로그에 테이블을 생성하고 있다고 표시되지만 실제로는 그렇지 않은 것 같습니다.

2
흐름을 제어하기 위해 예외를 사용하는 것은 다른 사람에게 가르치지 않고 부끄러운 일입니다. 그런 방식으로 메시지를 확인하면 이중으로.
Nick Cardoso 2018

아껴서 사용하면 위에서 설명한 것과 같은 사용 사례에서 예외를 사용하는 데 문제가 없다고 생각합니다. 나는 부끄러워하지 않는다.
robguinness

e.getMessage().contains("no such table")제어 흐름에 예외를 사용하는 것보다 나쁘다고 생각 합니다. 둘 다 나쁜 스타일이지만 특정 텍스트에 대한 오류 메시지를 구문 분석하는 것은 매우 나쁜 스타일입니다.
jox

11

이것이 내가 한 일입니다.

/* 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;

8

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


2

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

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


글쎄, 나는 getWritableDatabase () 호출을 통해 데이터베이스 객체를 얻고 있는데, 그것을 지정하는 것을 잊었다. 또한 해당 메서드에는 데이터베이스에서 볼 수없는 첫 번째 줄로 Log.d (...) 호출이 있기 때문에 onUpgrade ()가 호출되지 않는다고 확신합니다. ... 나는 전체 데이터베이스 파일을 삭제하려고합니다, 그리고 어떻게 든 그것을 해결되는지 우리가 나타납니다
camperdave

불행히도 전체 데이터베이스를 삭제하면 (루트 탐색기를 사용하여 파일을 제거했습니다) 작동하지 않았습니다. 내 앱에서 두 개의 테이블을 사용합니다. 하나는 완벽하게 초기화되었지만 다른 하나는 문제를 일으키지 않았습니다.
camperdave

2
 // @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 인 커서를 얻습니다.

0
 public boolean isTableExists(String tableName) {
    boolean isExist = false;
    Cursor cursor = db.rawQuery("select DISTINCT tbl_name from sqlite_master where tbl_name = '" + tableName + "'", null);
    if (cursor != null) {
        if (cursor.getCount() > 0) {
            isExist = true;
        }
        cursor.close();
    }
    return isExist;
}

0

no such table exists: error 같은 데이터베이스에서 테이블을 만들 때마다 하나의 테이블로 데이터베이스를 만들면이 오류가 발생하기 때문입니다.

이 오류를 해결하려면 새 데이터베이스를 만들어야하고 onCreate () 메서드 내에서 동일한 데이터베이스에 여러 테이블을 만들 수 있습니다.


0

중요한 조건은 IF NOT EXISTS 로 테이블이 이미 존재하는지 또는 데이터베이스에 없는지 확인하는 것입니다.

처럼...

String query = "CREATE TABLE IF NOT EXISTS " + TABLE_PLAYER_PHOTO + "("
            + KEY_PLAYER_ID + " TEXT,"
            + KEY_PLAYER_IMAGE + " TEXT)";
db.execSQL(query);

0

나는 그것을 직면하고 그것이 존재하지 않는 경우 테이블에서 내가 원하는 것을하는 것처럼 간단한 시도로 처리하여 오류가 발생하므로 예외로 잡아서 생성하십시오 :)

SQLiteDatabase db=this.getWritableDatabase();
        try{
            db.execSQL("INSERT INTO o_vacations SELECT * FROM vacations");
            db.execSQL("DELETE FROM vacations");
        }catch (SQLiteException e){
            db.execSQL("create table o_vacations (id integer primary key ,name text ,vacation text,date text,MONTH text)");
            db.execSQL("INSERT INTO o_vacations SELECT * FROM vacations");
            db.execSQL("DELETE FROM vacations");
        }


-1

..... 토스트 t = Toast.makeText (context, "try ...", Toast.LENGTH_SHORT); t.show ();

    Cursor callInitCheck = db.rawQuery("select count(*) from call", null);

    Toast t2a = Toast.makeText(context, "count rows " + callInitCheck.getCount() , Toast.LENGTH_SHORT);
    t2a.show();

    callInitCheck.moveToNext();
    if( Integer.parseInt( callInitCheck.getString(0)) == 0) // if no rows then do
    {
        // if empty then insert into call

.....

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.