Muchas de las aplicaciones móviles que utilizamos a diario necesitan almacenar información directamente en el dispositivo. Piensa en una lista de tareas, la configuración de una aplicación, o incluso los datos descargados para usarlos sin conexión. La capacidad de guardar y recuperar estos datos, conocida como persistencia de datos, es fundamental en el desarrollo de aplicaciones Android. Al asegurar que los datos no se pierden al cerrar la app o que están disponibles sin necesidad de una conexión constante, mejoramos significativamente la experiencia del usuario.
https://www.youtube.com/watch?v=91s
Para abordar esta necesidad, el SDK de Android nos proporciona SQLite. SQLite es una base de datos relacional ligera que permite estructurar y gestionar datos de una manera muy similar a como lo hacemos con las clases y objetos en lenguajes como Kotlin. No es necesario ser un experto en bases de datos complejas para empezar a usarlo en Android.

Aunque Android ofrece otras opciones para el almacenamiento persistente, como Preferences DataStore o el almacenamiento interno/externo de archivos, SQLite se destaca cuando necesitamos una estructura de datos más compleja y relacional. Dominar los conceptos básicos de SQLite y su lenguaje de consulta, SQL, es un paso clave antes de explorar herramientas más avanzadas como la biblioteca Room, que se basa en SQLite pero simplifica muchas operaciones.
- Conceptos Fundamentales de Bases de Datos Relacionales
- ¿Qué es SQLite?
- Representación de Datos en SQLite: Esquema y Tipos
- Trabajando con SQLite en Android Studio: El Inspector de Bases de Datos
- Lectura de Datos con la Sentencia SELECT
- Funciones de Agregación y Valores Distintos
- Filtrado de Consultas con la Cláusula WHERE
- Agrupación, Ordenamiento y Limitación de Resultados
- Inserción, Actualización y Eliminación de Datos
- Preguntas Frecuentes sobre Bases de Datos en Android Studio
- Conclusión
Conceptos Fundamentales de Bases de Datos Relacionales
Si alguna vez has trabajado con una hoja de cálculo, tienes una buena analogía para entender una base de datos relacional. Una hoja de cálculo contiene distintas hojas, que podemos comparar con las tablas de una base de datos. Cada hoja (o tabla) tiene columnas que definen el tipo de información que se almacenará, y filas que representan elementos individuales con valores para cada columna.
Por ejemplo, en una tabla de 'Estudiantes', las columnas podrían ser 'id', 'nombre', 'especialización' y 'calificación'. Cada fila contendría los datos de un estudiante específico.
Una Base de Datos Relacional funciona de manera similar:
- Tablas: Definen agrupaciones de datos de alto nivel, como 'estudiantes', 'profesores', 'cursos'.
- Columnas: Definen los atributos o tipos de datos que contiene cada fila de una tabla.
- Filas: Contienen los datos reales, con valores específicos para cada columna.
Esta estructura se mapea bien con la programación orientada a objetos. Una clase en Kotlin, como data class Student(id: Int, name: String, major: String, gpa: Double), es comparable a una tabla. Las propiedades de la clase (id, name, major, gpa) son como las columnas, y cada objeto (instancia de la clase) es como una fila.
Lo que distingue a una base de datos relacional es su capacidad para modelar relaciones entre tablas. Esto se logra mediante identificadores únicos.
Cada tabla relacional suele tener una columna que identifica de forma única cada fila. Este identificador se conoce como la Clave Primaria. A menudo, es un número entero que se incrementa automáticamente.
Cuando una tabla hace referencia a la Clave Primaria de otra tabla para mostrar una relación (por ejemplo, una tabla de 'Cursos' podría tener una columna 'profesor_id' que referencia la clave primaria de la tabla 'Profesores'), esta columna se conoce como una Clave Externa. La presencia de claves externas es lo que establece las relaciones entre tablas.
¿Qué es SQLite?
SQLite es el motor de base de datos relacional utilizado por Android para el almacenamiento local y persistente de datos. Es una biblioteca escrita en lenguaje C, muy ligera y eficiente, que permite gestionar bases de datos relacionales utilizando SQL (Structured Query Language), a veces pronunciado como 'sícuel'.
SQL no es un lenguaje de programación de propósito general como Kotlin o Java, sino un lenguaje diseñado específicamente para interactuar con bases de datos relacionales. Permite realizar operaciones como consultar (leer), insertar, actualizar y eliminar datos con sentencias relativamente sencillas.
Es importante notar que no todas las bases de datos son relacionales (organizadas en tablas, columnas y filas). Existen bases de datos NoSQL, que usan otros modelos como documentos (JSON), clave-valor, o grafos. Ejemplos mencionados en el texto incluyen Redis (clave-valor) o Cloud Firestore (documentos), pero SQLite es la opción relacional nativa en Android.
Representación de Datos en SQLite: Esquema y Tipos
Al igual que Kotlin tiene sus tipos de datos (Int, String, Boolean, Double), SQLite también define tipos de datos para las columnas de sus tablas. La estructura de las tablas y columnas en una base de datos se conoce como el esquema.
Aquí tienes una tabla que muestra la correspondencia entre algunos tipos de datos comunes de Kotlin y sus equivalentes en SQLite:
| Tipo de datos de Kotlin | Tipo de datos de SQLite |
|---|---|
| Int | INTEGER |
| String | VARCHAR o TEXT |
| Boolean | BOOLEAN (a menudo se almacena como INTEGER 0 o 1) |
| Float, Double | REAL |
Entender esta correspondencia es crucial al diseñar el esquema de tu base de datos en Android.
Trabajando con SQLite en Android Studio: El Inspector de Bases de Datos
Android Studio proporciona una herramienta muy útil para interactuar directamente con las bases de datos SQLite de tus aplicaciones en ejecución: el Database Inspector (Inspector de Bases de Datos). Esta herramienta te permite ver el esquema de la base de datos, examinar los datos en las tablas y ejecutar sentencias SQL directamente.
Para usarlo, simplemente ejecuta tu aplicación en un emulador o dispositivo conectado. Luego, ve a View > Tool Windows > App Inspection. En la ventana de App Inspection, selecciona la pestaña Database Inspector. Podrás ver una lista de las bases de datos de tu aplicación y, al seleccionar una, verás sus tablas. Puedes abrir una pestaña de consulta para escribir y ejecutar comandos SQL.
Consideremos la base de datos de ejemplo mencionada en el texto, que simula una aplicación de correo electrónico. Tiene una tabla llamada email con las siguientes columnas:
id: La Clave Primaria, un entero único para cada correo.subject: El asunto del correo (TEXT/VARCHAR).sender: La dirección de correo del remitente (TEXT/VARCHAR).folder: La carpeta donde se encuentra el correo ('inbox', 'spam', etc.) (TEXT/VARCHAR).starred: Indica si el correo está destacado (BOOLEAN, almacenado como INTEGER 0 o 1).read: Indica si el correo ha sido leído (BOOLEAN, almacenado como INTEGER 0 o 1).received: La marca de tiempo de recepción (INTEGER o REAL, dependiendo del formato, a menudo se usa INTEGER para timestamps Unix).
Esta estructura define el esquema de nuestra tabla email.
Lectura de Datos con la Sentencia SELECT
La operación más común en una base de datos es la lectura de datos. Para esto, utilizamos la sentencia SELECT de SQL. Una sentencia SELECT básica nos permite recuperar información de una o varias columnas de una tabla.

La sintaxis general es: SELECT nombre_columna(s) FROM nombre_tabla;
Puedes seleccionar una columna específica:
SELECT subject FROM email;Esto devolverá una lista con los asuntos de todos los correos electrónicos presentes en la tabla.
Puedes seleccionar varias columnas separándolas por comas:
SELECT subject, sender FROM email;Esto te dará una lista de pares (asunto, remitente) para cada correo.
Si quieres seleccionar *todas* las columnas de la tabla, puedes usar el carácter comodín *:
SELECT * FROM email;Esta consulta devolverá todas las filas y todas las columnas de la tabla email. Cada sentencia SQL generalmente termina con un punto y coma (;), aunque algunas herramientas como el Database Inspector pueden permitir omitirlo.
Funciones de Agregación y Valores Distintos
SQL no solo permite seleccionar datos brutos, sino también realizar cálculos o resúmenes sobre ellos utilizando funciones de agregación. Estas funciones operan sobre un conjunto de filas y devuelven un único valor.
Algunas funciones de agregación comunes son:
COUNT(): Cuenta el número de filas que cumplen un criterio.SUM(): Calcula la suma de los valores en una columna numérica.AVG(): Calcula el promedio de los valores en una columna numérica.MIN(): Encuentra el valor mínimo en una columna.MAX(): Encuentra el valor máximo en una columna.
Puedes usar COUNT(*) para saber cuántas filas hay en una tabla:
SELECT COUNT(*) FROM email;Para encontrar la marca de tiempo más reciente de recepción, podrías usar MAX() en la columna received:
SELECT MAX(received) FROM email;A veces, al seleccionar valores de una columna, te encontrarás con duplicados. La palabra clave DISTINCT te permite obtener solo los valores únicos.
Por ejemplo, para ver una lista de todos los remitentes únicos en la base de datos:
SELECT DISTINCT sender FROM email;Puedes combinar DISTINCT con funciones de agregación. Para contar cuántos remitentes únicos hay:
SELECT COUNT(DISTINCT sender) FROM email;Esto es mucho más eficiente que seleccionar todos los remitentes y contarlos manualmente en tu código Kotlin.
Filtrado de Consultas con la Cláusula WHERE
A menudo, no querrás ver *todos* los datos de una tabla, sino solo aquellos que cumplen ciertas condiciones. Para esto, usamos la cláusula WHERE. Se añade después de la cláusula FROM y especifica la condición que deben cumplir las filas para ser incluidas en el resultado.
Sintaxis: SELECT column(s) FROM table WHERE condition;
La condición es una expresión booleana. Solo las filas para las que la expresión es verdadera se incluirán en el resultado.
Para obtener todos los correos que están en la carpeta 'inbox':
SELECT * FROM email WHERE folder = 'inbox';Nota importante: en SQL, el operador de igualdad es un solo signo igual (=), a diferencia de Kotlin (==). Las cadenas de texto se delimitan con comillas simples (' ').
Puedes combinar múltiples condiciones usando operadores lógicos:
AND: Ambas condiciones deben ser verdaderas (equivalente a&&en Kotlin).OR: Al menos una condición debe ser verdadera (equivalente a||en Kotlin).NOT: Niega la condición (equivalente a!en Kotlin).
Para obtener correos no leídos que están en la bandeja de entrada:
SELECT * FROM email WHERE folder = 'inbox' AND read = false;Para obtener correos en la carpeta 'important' O que estén destacados:
SELECT * FROM email WHERE folder = 'important' OR starred = true;Los operadores de comparación (<, <=, >, >=, !=) también se usan en la cláusula WHERE.
Una capacidad muy útil de la cláusula WHERE es la búsqueda de texto usando el operador LIKE y los caracteres comodín % (que representa cero o más caracteres) y _ (que representa un solo carácter).
Para encontrar correos donde el asunto contiene la palabra 'fool':
SELECT * FROM email WHERE subject LIKE '%fool%';El % al principio y al final indica que puede haber cualquier número de caracteres antes o después de 'fool'.
Para encontrar correos donde el remitente comienza con la letra 'h':
SELECT * FROM email WHERE sender LIKE 'h%';Agrupación, Ordenamiento y Limitación de Resultados
Además de filtrar, puedes querer organizar o limitar los resultados de tu consulta.
Agrupar Resultados con GROUP BY
La cláusula GROUP BY se utiliza a menudo en combinación con funciones de agregación. Permite agrupar filas que tienen el mismo valor en una o más columnas, y luego aplicar la función de agregación a cada grupo por separado.
Sintaxis: SELECT column(s), aggregate_function(column) FROM table GROUP BY column(s);
Para contar cuántos correos hay en cada carpeta:
SELECT folder, COUNT(*) FROM email GROUP BY folder;Esto te devolverá una lista de pares (nombre_carpeta, cantidad_correos_en_esa_carpeta).
Ordenar Resultados con ORDER BY
La cláusula ORDER BY te permite especificar el orden en que se devuelven las filas. Puedes ordenar por una o más columnas, de forma ascendente (ASC, que es el valor por defecto si no se especifica nada) o descendente (DESC).

Sintaxis: SELECT column(s) FROM table ORDER BY column(s) [ASC|DESC];
Para obtener todos los correos ordenados por fecha de recepción, del más reciente al más antiguo:
SELECT * FROM email ORDER BY received DESC;Si combinas WHERE y ORDER BY, la cláusula WHERE siempre va primero:
SELECT * FROM email WHERE subject LIKE '%fool%' ORDER BY received ASC;Limitar Resultados con LIMIT
Si solo necesitas un subconjunto de los resultados, puedes usar la cláusula LIMIT para especificar el número máximo de filas a devolver. Esto es útil para paginación.
Sintaxis: SELECT column(s) FROM table LIMIT count;
O con un desplazamiento:
Sintaxis: SELECT column(s) FROM table LIMIT count OFFSET offset;
Para obtener los 10 correos más recientes de la bandeja de entrada:
SELECT * FROM email WHERE folder = 'inbox' ORDER BY received DESC LIMIT 10;Para obtener los siguientes 10 correos (la segunda 'página'):
SELECT * FROM email WHERE folder = 'inbox' ORDER BY received DESC LIMIT 10 OFFSET 10;La cláusula LIMIT (con o sin OFFSET) siempre va al final de la sentencia SELECT.
Inserción, Actualización y Eliminación de Datos
Además de leer, las bases de datos permiten modificar los datos almacenados.
Insertar Datos con INSERT
La sentencia INSERT se utiliza para añadir nuevas filas a una tabla.
Sintaxis: INSERT INTO table_name (column1, column2, ...) VALUES (value1, value2, ...);
O, si proporcionas valores para *todas* las columnas en el orden correcto:
Sintaxis: INSERT INTO table_name VALUES (value1, value2, ...);
Para añadir un nuevo correo a la tabla email, permitiendo que la Clave Primariaid se genere automáticamente (usando NULL) y usando la marca de tiempo actual (CURRENT_TIMESTAMP):
INSERT INTO email VALUES (NULL, 'Correo Nuevo Importante', '[email protected]', 'inbox', false, false, CURRENT_TIMESTAMP);Después de ejecutar esta sentencia, una nueva fila con los datos especificados se añadirá a la tabla email.
Actualizar Datos con UPDATE
La sentencia UPDATE se utiliza para modificar valores existentes en una o más filas de una tabla.
Sintaxis: UPDATE table_name SET column1 = value1, column2 = value2, ... WHERE condition;
La cláusula WHERE es crucial aquí, ya que especifica qué filas se actualizarán. Si omites la cláusula WHERE, ¡actualizarás *todas* las filas de la tabla!
Para marcar como leído el correo que acabamos de insertar (suponiendo que su id es 44):
UPDATE email SET read = true WHERE id = 44;Puedes verificar el cambio seleccionando esa fila:
SELECT * FROM email WHERE id = 44;Verás que el valor en la columna read ha cambiado a 1 (que representa true en SQLite BOOLEAN).
Eliminar Datos con DELETE
La sentencia DELETE se utiliza para eliminar una o más filas de una tabla.
Sintaxis: DELETE FROM table_name WHERE condition;
Al igual que con UPDATE, la cláusula WHERE es muy importante. ¡Sin ella, borrarás *todas* las filas de la tabla!
Para eliminar el correo con id 44:
DELETE FROM email WHERE id = 44;Puedes confirmar que se eliminó intentando seleccionarlo de nuevo:
SELECT * FROM email WHERE id = 44;No se devolverán filas si la eliminación fue exitosa.
Preguntas Frecuentes sobre Bases de Datos en Android Studio
Aquí respondemos algunas preguntas comunes sobre el uso de bases de datos en Android Studio:
¿Qué sistema de base de datos viene integrado en Android Studio?
Android Studio, a través del SDK de Android, utiliza SQLite como su motor de base de datos relacional integrado para el almacenamiento local de datos.
¿Qué es SQLite?
SQLite es una biblioteca de base de datos relacional ligera, de código abierto y empotrada (significa que se integra directamente en la aplicación, no requiere un servidor separado) que permite almacenar datos estructurados en archivos en el dispositivo Android.
¿Qué es SQL y por qué lo necesito para SQLite?
SQL (Structured Query Language) es el lenguaje estándar utilizado para interactuar con bases de datos relacionales como SQLite. Te permite realizar operaciones esenciales como leer, insertar, actualizar y eliminar datos mediante comandos de texto.
¿Cómo puedo ver la base de datos de mi aplicación en Android Studio?
Puedes usar el Database Inspector (Inspector de Bases de Datos) en Android Studio. Lo encuentras en View > Tool Windows > App Inspection. Asegúrate de que tu aplicación esté corriendo en un emulador o dispositivo.
¿Es SQLite la única forma de almacenar datos en Android?
No. Android ofrece varias opciones de persistencia de datos dependiendo de tus necesidades, incluyendo Preferences DataStore para datos pequeños y tipados, almacenamiento interno/externo para archivos, y SQLite (a menudo facilitado por la biblioteca Room) para datos estructurados y relacionales. SQLite es la opción principal para bases de datos relacionales.
Conclusión
La persistencia de datos es una parte vital del desarrollo de aplicaciones Android, y SQLite proporciona una solución robusta y eficiente para el almacenamiento local de datos estructurados. Al entender los fundamentos de las bases de datos relacionales y dominar las sentencias básicas de SQL (SELECT, INSERT, UPDATE, DELETE, junto con cláusulas como WHERE, GROUP BY, ORDER BY, y LIMIT), adquieres el poder de gestionar la información dentro de tus aplicaciones de manera efectiva.
Aunque interactuar directamente con SQLite y SQL es posible, herramientas y bibliotecas como Room (construida sobre SQLite) simplifican aún más el proceso al reducir la cantidad de código repetitivo y manejar la conversión entre objetos Kotlin y filas de la base de datos. Sin embargo, una sólida comprensión de los principios subyacentes de SQLite y SQL es indispensable para utilizar estas herramientas de manera eficiente y depurar problemas.
Si quieres conocer otros artículos parecidos a Bases de Datos en Android Studio: SQLite y SQL puedes visitar la categoría Bases de datos.

Aprende mas sobre MySQL