0% encontró este documento útil (0 votos)
25 vistas

Base de Datos SQLite

SQLite es un gestor de bases de datos ligero que almacena toda la base de datos en un único archivo. Se usa comúnmente en aplicaciones móviles pequeñas y dispositivos con recursos limitados como Android. El documento explica cómo usar SQLite en Android, incluyendo la creación de una clase adaptadora para encapsular las interacciones con la base de datos y facilitar la inserción, eliminación y actualización de datos. También describe el uso de cursores para consultar la base de datos y obtener resultados.

Cargado por

mano2116
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
25 vistas

Base de Datos SQLite

SQLite es un gestor de bases de datos ligero que almacena toda la base de datos en un único archivo. Se usa comúnmente en aplicaciones móviles pequeñas y dispositivos con recursos limitados como Android. El documento explica cómo usar SQLite en Android, incluyendo la creación de una clase adaptadora para encapsular las interacciones con la base de datos y facilitar la inserción, eliminación y actualización de datos. También describe el uso de cursores para consultar la base de datos y obtener resultados.

Cargado por

mano2116
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como DOCX, PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 9

Base de datos SQLite

SQLite es un gestor de bases de datos relacional y es de código abierto, cumple con los
estándares, y es extremadamente ligero. Además guarda toda la base de datos en un único
fichero. Su utilidad es evidente en el caso de aplicaciones de pequeño tamaño, pues éstas
no requerirán la instalación adicional de ningún gestor de bases de datos. Esto también
será así en el caso de dispositivos empotrados con recursos limitados. Android incluye
soporte a SQLite, y en esta sección veremos cómo usarlo.

Por medio de SQLite podremos crear bases de datos relacionales independientes para
nuestras aplicaciones. Con ellas podremos almacenar datos complejos y estructurados.
Aunque el diseño de bases de datos quedará fuera del contenido de este curso, ya que
necesitaríamos de más tiempo para poder tratarlo, es conveniente resaltar el hecho de que
las mejores prácticas en este campo siguen siendo útiles en el caso de aplicaciones
Android. En particular, la normalización de datos para evitar redundancia es un paso muy
importante en el caso en el que estemos diseñando una base de datos para dispositivos con
recursos limitados.

En el caso del sistema Android, SQLite se implementa como una librería C compacta, en
lugar de ejecutarse en un proceso propio. Debido a ello, cualquier base de datos que
creemos será integrada como parte de su correspondiente aplicación. Esto reduce
dependencias externas, minimiza la latencia, y simplifica ciertos procesos como la
sincronización.

Nota
Las bases de datos de Android se almacenan en el
directorio /data/data/[PAQUETE]/databases/, donde [PAQUETE] es el paquete correspondiente
a la aplicación. Por defecto todas las bases de datos son privadas y tan sólo accesibles por la
aplicación que las creó.

Content Values
Para insertar nuevas filas en tablas haremos uso de objetos de la clase ContentValues.
Cada objeto de este tipo representa una única fila en una tabla y se encarga de emparejar
nombres de columnas con valores concretos. Hay que tener en cuenta que SQLite difiere de
muchos otros motores de bases de datos en cuanto al tipado de las columnas. La idea
básicamente es que los valores para las columnas no tienen por qué ser de un único tipo;
es decir, los datos en SQLite son débilmente tipados. La consecuencia de esto es que no es
necesario comprobar tipos cuando se asignan o extraen valores de cada columna de una
fila, con lo que se mejora la eficiencia.

Cursores
Los cursores son una herramienta fundamental en el tratamiento de información en
Android, y también cuando se trabaja con bases de datos. Por lo tanto, en esta sección
introducimos este concepto tan importante.

Cualquier consulta a una base de datos en Android devolverá un objeto de la clase Cursor.
Los cursores no contienen una copia de todos los resultados de la consulta, sino que más
bien se trata de punteros al conjunto de resultados. Estos objetos proporcionan un
mecanismo para controlar nuestra posición (fila) en el conjunto de resultados obtenidos
tras la consulta.
La clase Cursor incluye, entre otras, las siguientes funciones de navegación entre
resultados:

 moveToFirst: desplaza el cursor a la primera fila de los resultados de la consulta.


 moveToNext: desplaza el cursor a la siguiente fila.
 moveToPrevious: desplaza el cursor a la fila anterior.
 getCount: devuelve el número de filas del conjunto de resultados de la consulta.
 getColumnName: devuelve el nombre de la columna especificada mediante un índice que
se pasa como parámetro.
 getColumnNames: devuelve un array de cadenas conteniendo el nombre de todas las
columnas en el cursor.
 moveToPosition: mueve el cursor a la fila especificada.
 getPosition: devuelve el índice de la posición apuntada actualmente por el cursor.
A lo largo de esta sesión aprenderemos cómo realizar consultas a una base de datos y
como extraer valores o nombres de columnas concretos a partir de los cursores obtenidos
por medio de dichas consultas.

Trabajar con bases de datos SQLite


Suele considerarse una buena práctica el crear una clase auxiliar que nos facilite la
interacción con la base de datos. Se tratará de una clase de tipo adaptador, que creará una
capa de abstracción que encapsulará dichas interacciones. De esta forma podremos añadir,
eliminar o actualizar elementos en la base de datos sin necesidad de introducir ni una única
instrucción en SQL en el resto del código, permitiendo además que se hagan las
comprobaciones de tipos correspondientes.

Una clase de este tipo debería incluir métodos para crear, abrir o cerrar la base de datos.
También puede ser un lugar conveniente para publicar constantes estáticas relacionadas
con la base de datos, como por ejemplo constantes que almacenen el nombre de la tabla o
las diferentes columnas.

A continuación se muestra el código de lo que podría ser un adaptador para una base de
datos estándar. Incluye una extensión de la clase SQLiteOpenHelper, que será tratada
en más detalle en la siguiente sección, y que se utiliza para simplificar la apertura, la
creación y la actualización de la base de datos.

1 import android.content.Context;
import android.database.*;
2
import android.database.sqlite.*;
3 import android.database.sqlite.SQLiteDatabase.CursorFactory;
4 import android.util.Log;
5
6 public class MiAdaptadorBD {
7 private static final String NOMBRE_BASE_DATOS = "mibasededatos.db";
private static final String TABLA_BASE_DATOS = "mainTable";
8
private static final int VERSION_BASE_DATOS = 1;
9
10 // Nombre de la columna de clave primaria
11 public static final String CP_ID="_id";
12 // El nombre e índice de cada columna en la base de datos
13 public static final String COLUMNA_NOMBRE="nombre";
14 public static final int COLUMNA_INDICE = 1;
// PENDIENTE: crear campos adicionales para el resto de columnas
15
// de la base de datos
16
17 // Sentencia SQL para crear una nueva base de datos
18 private static final String CREAR_BASE_DATOS = "create table " +
19 TABLA_BASE_DATOS + " (" + CP_ID +
20 " integer primary key autoincrement, " +
21 COLUMNA_NOMBRE + " text not null);";
22
// Variable para almacenar la instancia de la base de datos
23 private SQLiteDatabase db;
24 // Contexto de la aplicación que está usando la base de datos
25 private final Context contexto;
26 // Clase helper, usada para crear o actualizar la base de datos
27 // (hablamos de ella en la siguiente sección)
private miHelperBD dbHelper;
28
29
// Crea la base de datos con ayuda del helper
30 public MiAdaptadorBD(Context _contexto) {
31 contexto = _contexto;
32 dbHelper = new miHelperBD(contexto, NOMBRE_BASE_DATOS, null,
33 VERSION_BASE_DATOS);
}
34
35
// Abre una base de datos ya existente
36 public MiAdaptadorBD open() throws SQLException {
37 db = dbHelper.getWritableDatabase();
38 return this;
39 }
40
41 // Cierra la base de datos, cuando ésta ya no va a ser utilizada
public void close() {
42 db.close();
43 }
44
45 // Método para insertar un elemento en la tabla de la base de datos
46 public int insertar(MiObjeto _miObjeto) {
47 // PENDIENTE: crear nuevos elementos ContentValues para representar
// al objeto e insertarlos en la base de datos
48
49
// Devolvemos el índice del nuevo elemento en la base de datos
50 return index;
51 }
52
53 // Método para eliminar un elemento de la tabla de la base de datos
54 // Devuelve un valor booleano indicando el éxito o no de la
// operación
55
public boolean eliminar(long _indiceFila) {
56 return db.delete(TABLA_BASE_DATOS, CP_ID + "=" + _indiceFila, null) > 0;
57 }
58
59 // Método para obtener un Cursor que apunte a todas las filas contenidas
// en la tabla de la base de datos
60 public Cursor obtenerTodos () {
61 return db.query(TABLA_BASE_DATOS, new String[] {CP_ID, COLUMNA_NOMBRE},
62 null, null, null, null, null);
63 }
64
65 // Método para obtener un elemento determinado de la base de datos
// a partir de su índice de fila
66 public MiObjeto getObjeto(long _indiceFila) {
67 // PENDIENTE: obtener un cursor a una fila de la base
68 // de datos y usar sus valores para inicializar una
69 // instancia de MiObjeto
70
71 return objectInstance;
}
72
73
// Método para actualizar un elemento de la tabla de la base de datos
74 public boolean actualizar(long _indiceFila, MiObjeto _miObjeto) {
75 // PENDIENTE: crear nuevos ContentValues a partir del objeto
76 // y usarlos para actualizar una fila en la tabla correspondiente
77
78 return true;
79 }
80
// Clase privada auxiliar para ayudar en la creación y actualización
81 // de la base de datos
82 private static class miHelperBD extends SQLiteOpenHelper {
83
84 public miHelperBD(Context contexto, String nombre,
85 CursorFactory factory, int version) {
86 super(contexto, nombre, factory, version);
}
87
88
// Método llamado cuando la base de datos no existe en el disco
89 // y la clase Helper necesita crearla desde cero
90 @Override
91 public void onCreate(SQLiteDatabase _db) {
92 _db.execSQL(CREAR_BASE_DATOS);
}
93
94
// Método llamado cuando la versión de la base de
95 // datos en disco es diferente a la indicada; en
96 // este caso la base de datos en disco necesita ser
97 // actualizada
98 @Override
99 public void onUpgrade(SQLiteDatabase _db, int _versionAnterior,
100 int _versionNueva) {
// Mostramos en LogCat la operación
101
Log.w("AdaptadorBD", "Actualizando desde la versión " +
102 _versionAnterior + " a la versión " +
103 _versionNueva + ", lo cual borrará los datos
104 previamente almacenados");
105 // Actualizamos la base de datos para que se adapte a la nueva versión.
// La forma más sencilla de llevar a cabo dicha actualización es
106
// eliminar la tabla antigua y crear una nueva
107 _db.execSQL("DROP TABLE IF EXISTS " + TABLA_BASE_DATOS);
108 onCreate(_db);
109 }
110 }
111 }
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128

La clase SQLiteOpenHelper
La clase SQLiteOpenHelper es una clase abstracta utilizada como medio para
implementar un patrón de creación, apertura y actualización de una determinada base de
datos. Al implementar una subclase de SQLiteOpenHelper podemos abstraernos de la
lógica subyacente a la decisión de crear o actualizar una base de datos de manera previa a
que ésta deba ser abierta.

En el ejemplo de código anterior se vio cómo crear una subclase


de SQLiteOpenHelper por medio de la sobrecarga de sus
métodos onCreate y onUpgrade, los cuales permiten crear una nueva base de datos o
actualizar a una nueva versión, respectivamente.

Nota
En el ejemplo anterior, el método onUpgrade simplemente eliminaba la tabla existente y la
reemplazaba con la nueva definición de la misma. En la práctica la mejor solución sería migrar los
datos ya existentes a la nueva tabla.
Mediante los métodos getReadableDatabase y getWritableDatabase podemos abrir y
obtener una instancia de la base de datos de sólo lectura o de lectura y escritura
respectivamente. La llamada a getWritableDatabase podría fallar debido a falta de
espacio en disco o cuestiones relativas a permisos, por lo que es una buena práctica tener
en cuenta esta posibilidad por medio del mecanismo de manejo de excepciones de Java. En
caso de fallo la solución podría pasar por al menos proporcionar una copia de sólo lectura,
tal como se muestra en el siguiente ejemplo:

1 dbHelper = new miHelperBD(contexto, NOMBRE_BASE_DATOS, null, VERSION_BASE_DATOS);


2
SQLiteDatabase db;
3
try {
4 db = dbHelper.getWritableDatabase();
5 } catch (SQLiteException ex) {
6 db = dbHelper.getReadableDatabase();
7 }
8
Al hacer una llamada a cualquiera de los dos métodos anteriores se invocarán los
manejadores de evento adecuados. Así pues, si por ejemplo la base de datos no existiera
en disco, se ejecutaría el código de onCreate. Si por otra parte la versión de la base de
datos se hubiera modificado, se dispararía el manejador onUpgrade. Lo que sucede
entonces es que al hacer una llamada
a getWritableDatabase o getReadableDatabase se devolverá una base de datos
nueva, actualizada o ya existente, según el caso.

Crear una base de datos sin SQLiteHelper


También es posible crear y abrir bases de datos sin necesidad de utilizar una subclase
de SQLiteHelper. Para ello haremos uso del método openOrCreateDatabase. En este
caso será necesario también hacer uso del método execSQL sobre la instancia de la base
de datos devuelta por el método anterior para ejecutar los comandos SQL que permitirán
crear las tablas de la base de datos y establecer las relaciones entre ellas. El siguiente
código muestra un ejemplo:

1 private static final String NOMBRE_BASE_DATOS = "mibasededatos.db";


private static final String TABLA_BASE_DATOS = "tablaPrincipal";
2
3
private static final String CREAR_BASE_DATOS =
4 "create table " + TABLA_BASE_DATOS + " /_id integer primare key autoincrement," +
5 "columna_uno text not null);";
6
7 SQLiteDatabase db;
8
9 private void crearBaseDatos() {
db = openOrCreateDatabase(NOMBRE_BASE_DATOS, Context.MODE_PRIVATE, null);
10
db.execSQL(CREAR_BASE_DATOS);
11 }
12
13
Nota
Aunque no es necesariamente obligatorio, es recomendable que cada tabla incluya un campo de tipo
clave primaria con autoincremento a modo de índice para cada fila. En el caso en el que se desee
compartir la base de datos mediante un proveedor de contenidos, un campo único de este tipo es
obligatorio.

Realizar una consulta


El resultado de cualquier consulta a una base de datos será un objeto de la clase Cursor.
Esto permite a Android manejar los recursos de manera más eficiente, de tal forma que en
lugar de devolver todos los resultados, éstos se van proporcionando conforme se necesitan.

Para realizar una consulta a una base de datos haremos uso del método query de la
instancia correspondiente de la clase SQLiteDatabase. Los parámetros que requiere este
método son los siguientes:

 Un booleano opcional que permite indicar si el resultado debería contener tan sólo valores
únicos.
 El nombre de la tabla sobre la que realizar la consulta.
 Un array de cadenas que contenta un listado de las columnas que deben incluirse en el
resultado.
 Una cláusula where que defina las filas que se deben obtener de la tabla. Se puede utilizar
el comodín ?, el cual será reemplazado por los valores que se pasen a través del siguiente
parámetro.
 Un array de cadenas correspondientes a argumentos de selección que reemplazarán los
símbolos ? en la cláusula where.
 Una cláusula group by que define cómo se agruparán las filas obtenidas como resultado.
 Un filtro having que indique que grupos incluir en el resultado en el caso en el que se haya
hecho uso del parámetro anterior.
 Una cadena que describa la ordenación que se llevará a cabo sobre las filas obtenidas como
resultado.
 Una cadena opcional para definir un límite en el número de resultados a devolver.
Nota
Como se puede observar, la mayoría de estos parámetros hacen referencia al lenguaje SQL. Tratar
este tema queda fuera de los objetivos de este curso, por lo que en nuestros ejemplos le daremos en
la mayoría de las ocasiones un valor null a estos parámetros.

El siguiente código muestra un ejemplo de consultas utilizando diversos parámetros:

1 // Devolver los valores de las columnas uno y tres para todas las
// filas, sin duplicados
2
String[] columnas = new String[] {CLAVE_ID, CLAVE_COL1, CLAVE_COL3};
3
4 Cursor todasFilas = db.query(true, TABLA_BASE_DATOS, columnas, null, null, null,
5 null,
6 null, null);
7
8 // Devolvemos los valores de todas las columnas para aquellas filas cuyo valor de la
// columna 3 sea igual al de una determinada variable. Ordenamos las filas según el
9
// valor de la columna 5
10 // Como queremos los valores de todas las columnas, le damos al parámetro
11 // correspondiente a las columnas a devolver el valor null
12 // En este caso no se ha hecho uso del primer parámetro booleano, que es optativo
13 String where = CLAVE_COL3 + "=" + valor;
14 String orden = CLAVE_COL5;
Cursor miResultado = db.query(TABLA_BASE_DATOS, null, where, null, null, null,
15
orden);
16

Extraer resultados de un cursor


El primer paso para obtener resultados de un cursor será desplazarnos a la posición a partir
de la cual queremos obtener los datos, usando cualquiera de los métodos especificados
anteriormente (como por ejemplo moveToFirst o moveToPosition). Una vez hecho esto
hacemos uso de métodos get[TIPO]pasando como parámetro el índice de la columna.
Esto tendrá como resultado la devolución del valor para dicha columna de la fila
actualmente apuntada por el cursor:

1 String valor = miResultado.getString(indiceColumna);

A continuación podemos ver un ejemplo más completo, en el que se va iterando a lo largo


de los resultados apuntados por un cursor, extrayendo y sumando los valores de una
columna de flotantes:

1 int COLUMNA_VALORES_FLOTANTES = 2;
Cursor miResultado = db.query("Tabla", null, null, null, null, null, null);
2
float total = 0;
3
4 // Nos aseguramos de que se haya devuelto al menos una fila
5 if (miResultado.moveToFirst()) {
6 // Iteramos sobre el cursor
7 do {
float valor = miResultado.getFloat(COLUMNA_VALORES_FLOTANTES);
8
total += valor;
9 } while (miResultado.moveToNext());
10 }
11
12 float media = total / miResultado.getCount();
13
14
Nota
Debido a que las columnas de las bases de datos en SQLite son debilmente tipadas, podemos realizar
castings cuando sea necesario. Por ejemplo, los valores guardados como flotantes en la base de datos
podrían leerse más adelante como cadenas.

Añadir, actualizar y borrar filas


La clase SQLiteDatabase proporciona los métodos insert, delete y update, que
encapsulan las instrucciones SQL requeridas para llevar a cabo estas acciones. Además
disponemos de la posibilidad de utilizar el método execSQL, el cual nos permite ejecutar
cualquier sentencia SQL válida en nuestras tablas de la base de datos en el caso en el que
queramos llevar a cabo estas (u otras) operaciones manualmente.

Nota
Cada vez que modifiques los valores de la base de datos puedes actualizar un cursor que se pueda ver
afectado por medio del método refreshQuery de la clase Cursor.
Para insertar una nueva fila es necesario construir un objeto de la
clase ContentValues y usar su método put para proporcionar valor a cada una de sus
columnas. Para insertar la nueva fila pasaremos como parámetro este objeto del
tipo ContentValues al método insert de la instancia de la base de datos, junto por
supuesto con el nombre de la tabla. A continuación se muestra un ejemplo:

1 // Crear la nueva fila


ContentValues nuevaFila = new ContentValues();
2
3
// Asignamos valores a cada columna
4 nuevaFila.put(NOMBRE_COLUMNA, nuevoValor);
5 [.. Repetir para el resto de columnas ..]
6
7 // Insertar la nueva fila en la tabla
8 db.insert(TABLA_BASE_DATOS, null, nuevaFila);
9
Nota
Los ficheros, como imágenes o ficheros de audio, no se suelen almacenar dentro de tablas en una
base de datos. En estos casos se suele optar por almacenar en la base de datos una cadena con la
ruta al fichero o una URI.

La operación de actualizar una fila también puede ser llevada a cabo por medio del uso de
la clase ContentValues. En este caso deberemos llamar al método update de la instancia
de la base de datos, pasando como parámetro el nombre de la tabla, el
objeto ContentValues y una cláusula where que especifique la fila o filas a actualizar, tal
como se puede ver en el siguiente ejemplo:

1 // Creamos el objeto utilizado para definir el contenido a actualizar


ContentValues valoresActualizar = new ContentValues();
2
3
// Asignamos valores a las columnas correspondientes
4 valoresActualizar.put(NOMBRE_COLUMNA, nuevoValor);
5 [.. Repetir para el resto de columnas a actualizar ..]
6
7 String where = CLAVE_ID + "=" + idFila;
8
9 // Actualizamos la fila con el índice especificado en la instrucción anterior
db.update(TABLA_BASE_DATOS, valoresActualizar, where, null);
10
11
Por último, para borrar una fila, simplemente llamaremos al método delete de la
instancia de la base de datos, especificando en este caso el nombre de la tabla que se verá
afectada por la operación y una cláusula where que utilizaremos para especificar las filas
que queremos borrar. Un ejemplo podría ser el siguiente:

1 db.delete(TABLA_BASE_DATOS, CLAVE_ID + "=" + idFila, null);

También podría gustarte