Introdução ao SQLite em Android
Introdução ao SQLite em Android
Bases de Dados
Primeiros passos com SQLite
Nos próximos tópicos deste tutorial de programação Android, vamos nos deter em
describir las distintas opciones de acceso a datos que proporciona la plataforma y en cómo
podemos realizar as tarefas mais habituais dentro deste apartado.
Nos próximos tópicos, nos concentraremos na primeira opção, SQLite, que abrangerá
todas las tareas relacionadas con el almacenamiento de los datos propios de nuestra
aplicação. O segundo dos mecanismos, os Content Providers, que trataremos mais
avante, nos facilitarão a tarefa de tornar esses dados visíveis para outras aplicações e, de forma
recíproca, de permitir a consulta de dados publicados por terceiros a partir da nossa aplicação.
SQLiteé um motor de banco de dados muito popular atualmente por oferecer características
tão interessantes quanto o seu pequeno tamanho, não precisar de servidor, exigir pouca configuração,
sertransacionale, claro, ser de código livre.
En Android, la forma típica para crear, actualizar, y conectar con una base de datos SQLite
será através de uma classe auxiliar chamadaSQLiteOpenHelper, ou para ser mais exato, de
una clase propia que derive de ella y que debemos personalizar para adaptarnos a las
necessidades concretas da nossa aplicação.
Como exemplo, nós vamos criar uma base de dados muito simples chamada
BDUsuarios, com uma única tabela chamada Usuários que conterá apenas dois campos: nome
e email. Para eles, vamos criar uma classe derivada deSQLiteOpenHelperque
chamaremosUsuariosSQLiteHelper, onde sobrescreveremos os métodos
onCreate()yonUpgrade()para adaptarlos a la estructura de datos indicada:
package [Link];
importar [Link];
importar [Link];
importar [Link];
import [Link];
@Override
public void onCreate(SQLiteDatabase db) {
//Se ejecuta la sentencia SQL de creación de la tabla
[Link](sqlCreate);
}
@Override
public void onUpgrade(SQLiteDatabase db, int versãoAnterior,
int versãoNova) {
//NOTA: Por simplicidade do exemplo aqui utilizamos diretamente
// a opção de eliminar a tabela anterior e criá-la novamente
// vazio com o novo formato.
// No entanto, o normal será que seja necessário migrar dados da
// tabela antiga para a nova, pelo que este método deve
// ser mais elaborado.
Um exemplo prático: imaginemos que publicamos um aplicativo que utiliza uma tabela com os
campos usuario e email (llamémoslo versión 1 de la base de datos). Más adelante, ampliamos
a funcionalidade da nossa aplicação e precisamos que a tabela também inclua um campo
adicional por exemplo com a idade do usuário (versão 2 da nossa base de dados). Pois bem,
para que tudo funcione corretamente, da primeira vez que executarmos a versão ampliada de
na aplicação, precisaremos modificar a estrutura da tabela Usuários para adicionar o novo
campo idade. Pois este tipo de coisas são as que se encarregará de fazer automaticamente o
métodoonUpgrade()quando tentarmos abrir uma versão concreta do banco de dados
que ainda não exista. Para isso, como parâmetros, recebe a versão atual do banco de dados em
o sistema, e a nova versão à qual se deseja converter. Em função dessa dupla de dados
precisaremos realizar umas ações ou outras. No nosso caso de exemplo, optamos pela
opción más sencilla: borrar la tabla actual y volver a crearla con la nueva estructura, pero
como se indica nos comentários do código, o habitual será que precisemos de algo mais de
lógica para convertir la base de datos de una versión a otra y por supuesto para conservar los
dados registrados até o momento.
Uma vez definida nossa classe helper, a abertura do banco de dados a partir de nossa aplicação
resulta ser algo de lo mais simples. O primeiro será criar um objeto da classe
UsuariosSQLiteHelperao qual passaremos o contexto da aplicação (no exemplo uma
referencia a la actividad principal), el nombre de la base de datos, un objeto
CursorFactoryque tipicamente não será necessário (nesse caso passaremos o valornull),
e por último a versão do banco de dados que precisamos. A simples criação deste objeto
pode ter vários efeitos:
Se a base de dados já existir e sua versão atual coincidir com a solicitada, simplesmente
a conexão com ela será realizada.
Se a base de dados existir mas a sua versão atual for anterior à solicitada, será chamada
automaticamente ao métodoonUpgrade()para converter o banco de dados para a
nova versão e se conectará com o banco de dados convertido.
Se a base de dados não existir, o método onCreate() será chamado automaticamente para
criá-la e ela se conectará com o banco de dados criado.
importar [Link];
importar [Link];
importar [Link];
SQLiteDatabase db = [Link]();
Ok, e agora o que? Onde está o banco de dados que acabamos de criar? Como podemos
verificar se tudo correu bem e se os registros foram inseridos corretamente? Vamos lá
por partes.
En primer lugar veamos dónde se ha creado nuestra base de datos. Todas las bases de datos
SQLite criadas por aplicativos Android são armazenadas na memória do telefone em um
arquivo com o mesmo nome do banco de dados localizado em um caminho que segue o seguinte
padrão:
/data/data/[Link]/databases/nome_base_dados
/data/data/[Link]/databases/DBUsuarios
Para comprovar isso, podemos fazer o seguinte. Uma vez executado pela primeira vez desde
Eclipse a aplicação de exemplo no emulador do Android (e, claro, antes de
fechá-lo) podemos ir à perspectiva "DDMS" (Dalvik Debug Monitor Server) do Eclipse e na
Na aba "Explorador de Arquivos", poderemos acessar o sistema de arquivos do emulador, onde
podemos buscar a rota indicada do banco de dados. Podemos ver isso no seguinte
imagen:
Com isso, já verificamos pelo menos que o arquivo do nosso banco de dados foi criado na
rota correta. Já só nos resta verificar que tanto as tabelas criadas quanto os dados
inseridos também foram incluídos corretamente na base de dados. Para isso, podemos
recorrer a dois possíveis métodos:
O primeiro dos métodos é simples. O arquivo do banco de dados podemos transferi-lo para
nosso PC utilizando o botão de download localizado no canto superior direito do
explorador de arquivos (destacado em vermelho na imagem anterior). Ao lado deste botão
aparecem outros dois para fazer a operação contrária (copiar um arquivo local para o sistema de
arquivos do emulador) e para eliminar arquivos do emulador. Uma vez baixado o arquivo para
nosso sistema local, podemos usar qualquer administrador de SQLite para abrir e
consultar la base de datos, por ejemplo Administrador SQLite(gratuito).
O segundo método utiliza uma estratégia diferente. Em vez de baixar o banco de dados para
nosso sistema local, somos nós que acessamos remotamente o emulador a
através de sua consola de comandos (shell). Para isso, com o emulador de Android ainda aberto,
devemos abrir um console do MS-DOS e utilizar a utilidade [Link] (Android Debug Bridge)
situada na pastaferramentas de plataformado SDK do Android (no meu caso:c:\android-
sdk-windows\ferramentas-da-plataforma\). Em primeiro lugar, consultaremos os identificadores de
todos os emuladores em execução através do comando “dispositivos adb. Isso nos deve
devolver uma única instância se tivermos apenas um emulador aberto, que no meu caso particular se
chamaemulador-5554“.
Após conhecer o identificador do nosso emulador, vamos acessar seu shell através do
comandoadb -s identificador-do-emulador shell. Uma vez conectados, já
podemos acceder a nuestra base de datos utilizando el comando sqlite3passando a rota
do arquivo, para nosso exemplosqlite3 /data/data/[Link]/
bancos de dados/DBUsuarios. Se tudo correu bem, deve aparecer o prompt do SQLite
“sqlite>o que nos indicará que já podemos escrever as consultas SQL necessárias sobre
nossa base de dados. Nós vamos verificar se existe a tabela Usuários e se foram
inseridos os cinco registros de exemplo. Para isso faremos a seguinte consulta: “SELECIONAR *
DE Usuarios;“. Si todo es correcto esta instrucción debe devolvernos los cinco usuarios
existentes en la tabla. En la imagen siguiente se muestra todo el proceso descrito:
Con esto ya hemos comprobado que nuestra base de datos se ha creado correctamente, que
todos os registros de exemplo foram inseridos e tudo funciona como esperado.
Insertar/Actualizar/Eliminar
A API do SQLite do Android fornece duas alternativas para realizar operações sobre a
base de dados que não retornam resultados (entre elas a inserção/atualização/exclusão
de registros, mas também a criação de tabelas, de índices, etc).
O primeiro deles, que já comentamos brevemente na seção anterior, é o método
execSQL()da classeSQLiteDatabaseEste método permite executar qualquer
sentença SQL sobre a base de dados, desde que esta não retorne resultados. Para isso,
simplesmente aportaremos como parâmetro de entrada deste método a cadeia de texto
correspondente com a sentença SQL. Quando criamos o banco de dados no post anterior já
vimos algum exemplo disso para inserir os registros de teste. Outros exemplos poderiam ser
os seguintes:
//Inserir um registro
[Link]("INSERT INTO Usuarios (usuario,email) VALUES ")
('usu1','usu1@[Link]')
//Eliminar un registro
[Link]("DELETE FROM Usuarios WHERE usuario='usu1' ");
Atualizar um registro
[Link]("UPDATE Usuarios SET email='nuevo@[Link]' WHERE usuario='usu1'")
");
Como vemos, volvemos a pasar como primer parámetro el nombre de la tabla y en segundo
lugar a condiçãoONDE. Claro, se não precisássemos de nenhuma condição, poderíamos
deixar comonullneste parâmetro.
Um último detalhe sobre esses métodos. Tanto no caso deexecSQL()como nos casos
deatualizar()odeletar()podemos utilizar argumentos dentro das condições da
sentença SQL. Isto não são mais do que partes variáveis da sentença SQL que forneceremos em
desagrupar valores separados, o que nos evitará passar pela situação típica em que temos
que construir una sentencia SQL concatenando cadenas de texto y variables para formar el
comando SQL final. Esses argumentos SQL serão indicados com o símbolo '?’, e os valores de
esses argumentos devem ser passados no array na mesma ordem em que aparecem na sentença
SQL. Assim, por exemplo, podemos escrever instruções como a seguinte:
Esta forma de passar para a sentença SQL determinados dados variáveis pode nos ajudar
además a escribir código más limpio y evitar posibles errores.
En el siguiente apartado veremos cómo consultar la base de datos para recuperar registros
de acordo com um determinado critério.
Consultar/Recuperar registros
En el anterior apartado del curso vimos todas las opciones disponibles a la hora de insertar,
actualizar y eliminar datos de una base de datos SQLite en Android. En esta nueva entrega
vamos descrever a última das tarefas importantes de tratamento de dados que nos resta
por ver, a seleção e recuperação de dados.
De forma análoga a lo que vimos para las sentencias de modificación de datos, vamos a tener
duas opções principais para recuperar registros de um banco de dados SQLite no Android. A
a primeira delas utilizando diretamente um comando de seleção SQL, e como segunda
opção utilizando um método específico onde parametrizaremos a consulta ao banco de dados
datos.
Como no caso dos métodos de modificação de dados, também podemos adicionar a este
método uma lista de argumentos variáveis que tenhamos indicado no comando SQL com o
símbolo ' ?‘, por exemplo assim:
Mais adiante nesta seção, veremos como podemos manipular o objeto Cursor para
recuperar os dados obtidos.
Como segunda opción para recuperar datos podemos utilizar el método consulta()da classe
SQLiteDatabaseEste método recebe vários parâmetros: o nome da tabela, um array
com os nomes dos campos a recuperar, a cláusulaONDE, um array com os argumentos
variáveis incluídas noONDE(se houver, nullcaso contrário), a cláusula GROUP BY se
existe, a cláusulaTENDOse existe, e por último a cláusulaORDENAR PORsim existe.
Opcionalmente, pode-se incluir um parâmetro no final indicando o número máximo de
registros que queremos que nos devolva a consulta. Veamos o mesmo exemplo anterior
utilizando o métodoconsulta():
Como vemos, os resultados são devolvidos novamente em um objeto Cursor que devemos
recorrer para processar os dados obtidos.
Para percorrer e manipular o cursor retornado por qualquer um dos dois métodos mencionados
temos à nossa disposição vários métodos da classeCursor, entre os quais destacamos
dos dos dedicados a percorrer o cursor de forma sequencial e em ordem natural:
Uma vez posicionados em cada registro, poderemos utilizar qualquer um dos métodos.
getXXX(índice_coluna)existentes para cada tipo de dado para recuperar o dado de
cada campo do registro atual do cursor. Assim, se quisermos recuperar, por exemplo, o segundo
columna del registro actual, y ésta contiene un campo alfanumérico, haremos la llamada
getString(1)[NOTA: los índices comienzan por 0, por lo que la segunda columna tiene
índice 1], en caso de contener un dato de tipo real llamaríamos a getDouble(1), e de forma
análoga para todos os tipos de dados existentes. Com tudo isso em mente, vejamos como
poderíamos percorrer o cursor retornado pelo exemplo anterior: