Curso SQLite Crash para desarrolladores de Android

Las aplicaciones de Android pueden almacenar datos de aplicaciones en bases de datos SQLite. En este tutorial, aprenderá cómo se diseñan y manipulan las bases de datos SQLite..

Aquí comenzamos diseñando y utilizando una base de datos SQLite simple para administrar los puntajes de los torneos de ajedrez. Este tutorial es una breve descripción de cómo funcionan las bases de datos SQLite. Este conocimiento se utilizará en futuros tutoriales de desarrollo para implementar aplicaciones de Android basadas en bases de datos..

Empezando

Las aplicaciones de Android pueden crear y manipular sus propias bases de datos relacionales privadas de SQLite. Los desarrolladores también pueden inspeccionar y modificar las bases de datos en un emulador o dispositivo de Android determinado mediante la herramienta de línea de comandos sqlite3 provista como parte de la herramienta de Android SDK llamada Android Debug Bridge (adb).

En este tutorial, asumimos que usted tiene cierta comprensión de las bases de datos relacionales, en teoría, pero requiere un poco de un curso de actualización antes de usarlas dentro de sus aplicaciones de Android. Este tutorial particular no requiere ninguna herramienta; es más un ejercicio teórico.

Sin embargo, si planea desarrollar aplicaciones de Android que se basan en bases de datos SQLite, necesitará instalar las herramientas necesarias para el desarrollo de Android, como el SDK de Android y el IDE de Eclipse. Echa un vistazo a los muchos otros útiles tutoriales para Android disponibles aquí en Mobiletuts + para ayudarte a trabajar en estas tareas..

Que es SQLite?

SQLite es un motor de base de datos relacional ligero. SQLite es rápido y tiene un tamaño reducido, lo que lo hace perfecto para dispositivos Android. En lugar de las bases de datos basadas en servidores pesados ​​como Oracle y Microsoft SQL Server, cada base de datos SQLite se almacena dentro de un único archivo en el disco. Las aplicaciones de Android pueden optar por almacenar datos de aplicaciones privadas en una base de datos SQLite.

Nota: Si está familiarizado con SQL, entonces SQLite será muy fácil de aprender. SQLite es básicamente un motor de base de datos SQL reducido para dispositivos integrados. Para obtener información específica sobre SQLite y sus características, funcionalidad y limitaciones, consulte la documentación en línea de SQLite..

Una revisión rápida de los fundamentos de la base de datos

Una base de datos es simplemente una forma estructurada de almacenar datos de manera persistente. Los datos se almacenan en tablas. Una tabla tiene columnas con diferentes tipos de datos. Cada fila en una tabla representa un registro de datos. Puede resultarle útil pensar en una tabla como una hoja de cálculo de Excel. Para una perspectiva de programación orientada a objetos, cada tabla en una base de datos a menudo representa un objeto (representado por una clase). Cada columna de la tabla representa un atributo de clase. Cada registro en una tabla representa una instancia específica de ese objeto.

Veamos un ejemplo rápido. Digamos que usted tiene una base de datos de la empresa con una tabla llamada Empleado. La tabla Empleado puede tener cinco columnas con tipo: EmployeeID (número), Nombre (cadena), Apellido (cadena), Título (cadena) y Salario (número). Luego puede agregar un registro a la base de datos para un empleado llamado John Doe y un registro separado para un empleado llamado Anne Droid.

Los datos dentro de una base de datos deben ser inspeccionados y manipulados. Los datos dentro de una tabla pueden ser:

  • Agregado (usando el INSERTAR mando)
  • Modificado (usando el ACTUALIZAR mando)
  • Eliminado (usando el BORRAR mando)

Puede buscar datos específicos dentro de una base de datos utilizando lo que se llama una consulta. Una consulta (con el comando SELECT) puede incluir una tabla o varias tablas. Para crear una consulta, debe especificar las tablas, columnas de datos y valores de datos de interés mediante el lenguaje de comandos SQL. Cada comando SQL termina con un punto y coma (;).

La base de datos del torneo de ajedrez

La mejor manera de entender realmente cómo funcionan las bases de datos SQLite es trabajar con un ejemplo simple, así que hagámoslo. Supongamos que tenemos una aplicación que realiza un seguimiento de las puntuaciones de los jugadores en un torneo de ajedrez informal. Las puntuaciones de los jugadores se registran y luego, al final de una serie de partidos, se determina el ganador. La puntuación general de cada jugador en el torneo se calcula a partir de su rendimiento en:

  • Cuatro calentamientos de calentamiento (peso: 10% de la puntuación general cada uno)
  • Una semifinal (peso: 25% del puntaje general)
  • Una final (peso: 35% del puntaje general)

Nota: Para el torneo, los puntajes de los jugadores podrían basarse en una fórmula que tenga en cuenta el tiempo que llevó ganar el juego y el tipo y número de piezas que quedan en el tablero al final del juego. De esta manera, un jugador fuerte recibirá una alta puntuación por perder algunas piezas poderosas y ganar el juego rápidamente. Tal vez los jueces incluyen el estilo y la actitud para fomentar el juego divertido y ligero. La forma en que se calculan los puntajes no es realmente importante en la forma en que definimos nuestra base de datos; Simplemente los almacenamos en la base de datos. Para simplificar, asumiremos que las puntuaciones se basan en una escala de 0-100.

Diseñar el esquema de base de datos

Un esquema de base de datos es simplemente la definición de la estructura de la base de datos en términos de tablas, columnas de datos y demás. El esquema para nuestra base de datos de torneos es bastante simple:

El esquema de la base de datos TournamentScores tiene tres tablas:

  • La tabla de jugadores contiene información del jugador..
  • La tabla de Juegos contiene información sobre cada juego y cuánto cuenta para la puntuación global del torneo del jugador..
  • La tabla GameResults contiene las puntuaciones de todos los jugadores..

SQLite3 tiene soporte para los siguientes tipos de datos comunes para columnas:

  • ENTERO (enteros con signo)
  • REAL (valores de punto flotante)
  • TEXTO (Cadena UTF-8 o UTF-16; codificada mediante codificación de base de datos)
  • GOTA (fragmento de datos)

Una vez que haya determinado qué columnas son necesarias para cada tabla, estará listo para crear algunas tablas dentro del esquema de su base de datos.

Trabajando con Tablas

Comencemos por crear la tabla de jugadores. Esta tabla requiere una identificación de jugador única para hacer referencia a cada jugador. Podemos hacer que esta sea la clave principal (para identificar de forma única un registro en esta tabla) y establecer su atributo de autoincremento. Autoincrement significa que cada vez que se agregue un nuevo registro de jugador, el registro obtendrá una nueva y única identificación de jugador. También queremos almacenar el nombre y apellido de cada jugador, no se permiten nulos.
Aquí podemos usar la sentencia CREATE TABLE SQL para generar la tabla de jugadores:

CREAR TABLA Jugadores (id INTEGER PRIMARY KEY AUTOINCREMENT, fname TEXT NOT NULL, lname TEXT NOT NULL); 

La mesa de juegos es muy similar. Necesitamos una identificación de juego única para hacer referencia a cada juego. También queremos un nombre amistoso para cada juego y un valor de peso sobre cuánto cuenta el juego para la puntuación final del torneo del jugador (como porcentaje). Aquí está la declaración SQL para crear la tabla de juegos:

CREAR TABLA Juegos (id INTEGER PRIMARY KEY AUTOINCREMENT, gamename TEXT, peso REAL DEFAULT .10 CHECK (peso<=1)); 

También puede eliminar tablas utilizando la instrucción DROP TABLE. Por ejemplo, para eliminar la tabla Juegos, use el siguiente comando SQL:

DROP TABLE Juegos; 

Poblando tablas con registros de datos

Antes de continuar, agreguemos algunos datos a estas tablas. Para agregar un registro a la tabla de jugadores, debe especificar los nombres de las columnas y los valores en orden. Por ejemplo, la siguiente instrucción SQL usa el comando INSERT para agregar un registro para el jugador de ajedrez Bobby Fisher:

INSERTAR en los jugadores (fname, lname) VALUES ('Bobby', 'Fisher'); 

Mientras estamos en ello, agregaremos dos jugadores más: Bart Simpson (un jugador de ajedrez muy lamentable) y Garry Kasparov (quizás el mejor jugador de ajedrez de la historia). Al mismo tiempo, necesitamos agregar un montón de registros a la tabla de Juegos. Primero agregamos la semifinal, que cuenta con el 25 por ciento de la puntuación del torneo del jugador:

INSERTAR en los Juegos (nombre del juego, peso) VALORES ('Semifinal', .25); 

Luego agregamos un par de calentamientos de calentamiento, que utilizan el peso predeterminado del 10 por ciento:

INSERTAR en VALORES de los Juegos (nombre de juego) ('Calentamiento de Calentamiento 1'); 

Finalmente, agregamos un valor final del 35 por ciento del puntaje total del torneo:

INSERTAR en Juegos (nombre del juego, peso) VALORES ('Final', .35); 

Consultando tablas para resultados con SELECT

¿Cómo sabemos que los datos que hemos agregado están en la tabla? Bueno, eso es fácil. Simplemente consultamos todas las filas en una tabla usando una instrucción SELECT:

SELECT * FROM Games; 

Esto devuelve todos los registros en la tabla Juegos:

id nombre del juego peso ----- --------------- ------ 1 Semifinal 0.25 2 Calentamiento Calentamiento 1 0.1 3 Calentamiento Calentamiento 2 0.1 4 Calentamiento -up Heat 3 0.1 5 Heat-up Heat 4 0.1 6 Final 0.35 

Uso de alias de columnas y columnas calculadas

También podemos crear nuestras propias columnas y alias ellas. Por ejemplo, podemos crear un alias de columna llamado PlayerName que es una columna calculada: son los nombres y apellidos del jugador que se concatenaron usando el || Operador, separado por un espacio:

SELECCIONAR fname || "|| lname AS PlayerName, id FROM Players; 

Esta consulta produce los siguientes resultados:

ID de PlayerName ------------ - Bobby Fisher 1 Bart Simpsen 2 Garry Kasparov 3 

Alterar datos en tablas

El apellido de Bart (id del jugador 2) se deletrea incorrectamente. Para actualizar la tabla de jugadores para reflejar la ortografía correcta, puede usar el comando ACTUALIZAR:

ACTUALIZAR los jugadores SET lname = "Simpson" WHERE playerid = 2; 

Puede eliminar filas de una tabla usando la función DELETE. Por ejemplo, para eliminar el registro que acabamos de actualizar:

ELIMINAR DE LOS Jugadores DONDE playerid = 2; 

Puede eliminar todas las filas de una tabla al no especificar la cláusula WHERE:

ELIMINAR DE LOS JUGADORES; 

Uso de claves externas y claves compuestas

Ahora que tenemos todos nuestros jugadores y juegos configurados, creemos la tabla GameResults. Esta es una tabla más complicada. La tabla GameResults empareja los ID de jugadores de la tabla de Jugadores con los ID de juegos de la tabla de Juegos y luego enumera la puntuación que el jugador obtuvo para el juego específico. Las columnas, que se vinculan a otras tablas de esta manera, a menudo se llaman claves externas. Queremos combinaciones únicas entre jugadores y juegos, por lo que creamos una clave principal compuesta a partir de las claves externas del jugador y del juego, para identificar de forma única un registro de Resultados de Juego. Por último, exigimos que los puntajes sean números enteros entre 0 y 100..

CREAR TABLA Resultados del juego (playerid REFERENCIAS INTEGRALES Jugadores (id), gameid REFERENCIAS INTEGRALES Juegos (id), puntuación INTEGER CHECK (puntuación<=100 AND score>= 0), CLAVE PRIMARIA (playerid, gameid)); 

(Nota: SQLite no impone restricciones de clave externa, pero puede configurarlas de todas formas y aplicarlas mediante la creación de activadores).
Ahora es el momento de insertar algunos datos en la tabla GameResults. Digamos que Bobby Fisher (identificación del jugador 1) recibió una puntuación de 82 puntos en la semifinal (identificación del juego 1). Podría usar el siguiente comando SQL para insertar el registro apropiado en la tabla GameResults:

INSERTA en GameResults (playerid, gameid, score) VALUES (1,1,82); 

Ahora supongamos que el torneo se juega y los puntajes se agregan a la tabla de Resultados del juego. Bobby es un buen jugador, Bart es un jugador terrible y Garry siempre juega un juego perfecto. Una vez que los registros se hayan agregado a la tabla de Resultados de Juego, podemos ejecutar un comando SELECCIONAR * para listar todos los registros en la tabla, o podemos especificar columnas explícitamente de esta manera:

SELECCIONAR playerid, gameid, score FROM GameResults; 

Aquí están los resultados de esta consulta:

puntaje de jugador jugador puntaje ---------- ---------- ----- 1 1 82 1 2 88 1 3 78 1 4 90 1 5 85 1 6 94 2 1 10 2 2 60 2 3 50 2 4 55 2 5 45 2 6 65 3 6 100 3 5 100 3 4 100 3 3 100 3 2 100 3 1 100 

Como puede ver, este listado no es particularmente "legible por humanos".

Consultando en varias tablas usando JOIN

¿No sería más útil si se mostraran los nombres de los jugadores y los Juegos en lugar de sus identificaciones numéricas? La consulta y combinación de datos en sentencias SELECT a menudo se maneja realizando una ÚNICA con múltiples fuentes de tabla; Hay diferentes tipos de uniones. Cuando trabaja con varias tablas, necesita especificar a qué tabla pertenece una columna (especialmente cuando las columnas tienen el mismo nombre, como con todas estas columnas de ID diferentes). Puede referirse a las columnas por su nombre de columna o por su nombre de tabla, luego un punto (.) Y luego el nombre de columna.

Volvamos a enumerar las puntuaciones del jugador, solo que esta vez, incluiremos el nombre del juego y el nombre del jugador. Además, limitamos nuestros resultados solo al puntaje de la Final (id del juego 6):

SELECCIONA Players.fname || "|| Players.lname AS PlayerName, Games.gamename, GameResults.score FROM GameResults JOIN Players ON (GameResults.playerid = Players.id) JOIN Games ON (GameResults.gameid = Games.id) WHERE gameid = 6; 

lo que nos da los siguientes resultados (puede dejar el DÓNDE para obtener todos los Juegos):

Jugador Nombre del jugador puntuación del juego ------------------ -------------- ----- Final de Bobby Fisher 94 Final de Bart Simpson 65 Garry Kasparov Final 100 

Ejecutando consultas más complejas

El cielo es el límite cuando se trata de las consultas que puede realizar aquí. Para nuestro ejemplo, la consulta más importante es la que nos dice quién ganó el torneo..
Aquí está la consulta final para calcular las clasificaciones del torneo:

SELECCIONA Players.fname || "|| Players.lname AS PlayerName, SUM ((Games.weight * GameResults.score)) COMO TotalWeightedScore DE GameResults JOIN Players ON (GameResults.playerid = Players.id) JOIN Games ON (GameResults.gameid = Games.id) GROUP BY GameResults.playerid ORDER BY TotalWeightedScore DESC; 

Esta consulta recopila información de varias tablas diferentes mediante el uso de JOIN y calcula los resultados del torneo de forma legible. Así que echemos un vistazo a lo que hace esta consulta:

  • El nombre completo de cada jugador se muestra como la primera columna de resultados (calculado a partir de su nombre y apellido)
  • La puntuación del torneo de cada jugador se muestra como la segunda columna de resultados (calculada a partir de las puntuaciones ponderadas de todos los juegos jugados por un jugador determinado)
  • Los registros de resultados se enumeran en orden descendente según los puntajes del torneo (primer lugar, segundo lugar, etc.)

Los resultados de esta consulta se muestran a continuación:

PlayerName TotalWeightedScore ------------------------- ----------------- Garry Kasparov 100.0 Bobby Fisher 87.5 Bart Simpson 46.25 

Conclusión

Esto concluye nuestra exploración de un ejemplo simple de base de datos SQLite: una base de datos de torneos de ajedrez. Esperemos que haya vuelto a familiarizarse con conceptos de bases de datos relacionales como tablas, registros y consultas, y se haya familiarizado con muchos de los comandos SQLite de uso común. Finalmente, ha recorrido el diseño y el uso de una base de datos de ejemplo. Ahora que tiene una idea de cómo funcionan las bases de datos SQLite, está listo para usarlas dentro de sus aplicaciones de Android (el tema de nuestro próximo tutorial de esta serie).

Sobre los autores

Los desarrolladores de dispositivos móviles Lauren Darcey y Shane Conder han sido coautores de varios libros sobre el desarrollo de Android: un libro de programación en profundidad titulado Desarrollo de aplicaciones inalámbricas para Android y Sams TeachYourself Desarrollo de aplicaciones para Android en 24 horas. Cuando no están escribiendo, pasan su tiempo desarrollando software móvil en su empresa y brindando servicios de consultoría. Puede comunicarse con ellos por correo electrónico a [email protected], a través de su blog en androidbook.blogspot.com, y en Twitter @androidwireless.