Tenho um aplicativo para Android que precisa verificar se já existe um registro no banco de dados e, se não houver, processar algumas coisas e, eventualmente, inseri-lo e simplesmente ler os dados do banco de dados se os dados existirem. Estou usando uma subclasse de SQLiteOpenHelper para criar e obter uma instância regravável de SQLiteDatabase, que pensei que automaticamente se encarregaria de criar a tabela se ela ainda não existisse (já que o código para fazer isso está no onCreate (... ) método).
No entanto, quando a tabela ainda NÃO existe e o primeiro método executado no objeto SQLiteDatabase que tenho é uma chamada para consulta (...), meu logcat mostra um erro de "I / Database (26434): sqlite retornado: erro code = 1, msg = no such table: appdata ", e com certeza, a tabela appdata não está sendo criada.
Alguma ideia do porquê?
Estou procurando um método para testar se a tabela existe (porque se não existir, os dados certamente não estarão nela, e eu não preciso ler até que eu escreva nela, o que parece criar a tabela corretamente), ou uma maneira de garantir que ele seja criado, e apenas vazio, a tempo para a primeira chamada de consulta (...)
EDITAR
Isso foi postado após as duas respostas abaixo:
Acho que posso ter encontrado o problema. Por algum motivo, decidi que um SQLiteOpenHelper diferente deveria ser criado para cada tabela, embora ambos acessem o mesmo arquivo de banco de dados. Acho que refatorar esse código para usar apenas um OpenHelper e criar as duas tabelas dentro do onCreate pode funcionar melhor ...
cursor.close();
select * from sqlite_master where UPPER(name) = 'ROUTES'.
Não sei nada sobre a API Android SQLite, mas se você consegue falar com ela diretamente no SQL, pode fazer o seguinte:
create table if not exists mytable (col1 type, col2 type);
O que garantirá que a tabela seja sempre criada e não gerará nenhum erro se já existir.
fonte
Embora já existam muitas respostas boas para essa pergunta, eu encontrei outra solução que acho mais simples. Cerque sua consulta com um bloco try e a seguinte captura:
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. } }
Funcionou para mim!
fonte
e.getMessage().contains("no such table")
é pior do que usar exceções para o fluxo de controle. Ambos são estilos inadequados, mas analisar mensagens de erro para um texto específico é até mesmo um estilo muito ruim.Isso é o que eu fiz:
/* 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;
fonte
Sim, a teoria da minha edição estava certa: o problema que estava fazendo com que o método onCreate não rodasse era o fato de que os
SQLiteOpenHelper
objetos deveriam se referir a bancos de dados, e não ter um separado para cada tabela. Juntar as duas tabelas em uma sóSQLiteOpenHelper
resolveu o problema.fonte
Você mencionou que criou uma classe que estende
SQLiteOpenHelper
e implementa oonCreate
método. Você está certificando-se de que está executando todas as chamadas de aquisição de banco de dados com essa classe? Você só deve obterSQLiteDatabase
objetos por meio doSQLiteOpenHelper#getWritableDatabase
e,getReadableDatabase
caso contrário, oonCreate
método não será chamado quando necessário. Se você já está fazendo isso, verifique se oSQLiteOpenHelper#onUpgrade
método está sendo chamado. Nesse caso, o número da versão do banco de dados foi alterado em algum momento, mas a tabela nunca foi criada corretamente quando isso aconteceu.Como um aparte, você pode forçar a recriação do banco de dados, certificando-se de que todas as conexões com ele estejam fechadas e chamando
Context#deleteDatabase
e, em seguida, usando oSQLiteOpenHelper
para fornecer um novo objeto db.fonte
// @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; }
fonte
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; }
fonte
no such table exists: error
está chegando porque uma vez que você cria um banco de dados com uma tabela depois disso, sempre que você cria uma tabela no mesmo banco de dados dá esse erro.Para resolver este erro você deve criar um novo banco de dados e dentro do método onCreate () você pode criar várias tabelas no mesmo banco de dados.
fonte
A condição importante é IF NOT EXISTS para verificar a tabela já existe ou não no banco de dados
gostar...
String query = "CREATE TABLE IF NOT EXISTS " + TABLE_PLAYER_PHOTO + "(" + KEY_PLAYER_ID + " TEXT," + KEY_PLAYER_IMAGE + " TEXT)"; db.execSQL(query);
fonte
Enfrentei isso e lidei com isso tentando pegar tão simples quanto eu faço o que quero na tabela se não existir causará erro, então pegue pelas exceções e crie-o :)
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"); }
fonte
..... Toast 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
.....
fonte