Le applicazioni Android possono memorizzare i dati dell'applicazione nei database SQLite. In questo tutorial, si impara come i database SQLite sono progettati e manipolati.
Qui iniziamo progettando e utilizzando un semplice database SQLite per gestire i punteggi dei tornei di scacchi. Questo tutorial è inteso come una breve panoramica di come funzionano i database SQLite. Queste conoscenze verranno quindi utilizzate nelle esercitazioni di sviluppo future per implementare applicazioni Android basate su database.
Le applicazioni Android possono creare e manipolare i propri database relazionali SQLite privati. Gli sviluppatori possono anche ispezionare e modificare i database su un determinato emulatore o dispositivo Android utilizzando lo strumento da riga di comando sqlite3 fornito come parte dello strumento Android SDK denominato Android Debug Bridge (adb).
In questo tutorial, assumiamo che tu abbia una certa comprensione dei database relazionali, in teoria, ma richiedi un po 'di corso di aggiornamento prima di utilizzarli nelle tue applicazioni Android. Questo particolare tutorial non richiede strumenti; è più un esercizio teorico.
Tuttavia, se hai intenzione di sviluppare applicazioni Android che si basano su database SQLite, dovrai installare gli strumenti necessari per lo sviluppo di Android, come l'SDK di Android e l'IDE di Eclipse. Consulta le numerose e utili esercitazioni Android disponibili qui su Mobiletuts + per aiutarti a svolgere queste attività.
SQLite è un motore di database relazionale leggero. SQLite è veloce e ha un ingombro ridotto, che lo rende perfetto per i dispositivi Android. Invece dei database pesanti basati su server come Oracle e Microsoft SQL Server, ogni database SQLite è memorizzato all'interno di un singolo file su disco. Le applicazioni Android possono scegliere di archiviare i dati delle applicazioni private in un database SQLite.
Nota: se hai familiarità con SQL, SQLite sarà molto facile da imparare. SQLite è fondamentalmente un motore di database SQL semplificato per dispositivi embedded. Per informazioni specifiche su SQLite e le sue caratteristiche, funzionalità e limitazioni, consultare la documentazione in linea di SQLite.
Un database è semplicemente un modo strutturato di memorizzare i dati in modo persistente. I dati sono memorizzati nelle tabelle. Una tabella ha colonne con diversi tipi di dati. Ogni riga in una tabella rappresenta un record di dati. Potresti trovare utile pensare a una tabella come un foglio di calcolo di Excel. Per una prospettiva di programmazione orientata agli oggetti, ciascuna tabella in un database rappresenta spesso un oggetto (rappresentato da una classe). Ogni colonna della tabella rappresenta un attributo di classe. Ogni record in una tabella rappresenta un'istanza specifica di quell'oggetto.
Diamo un'occhiata ad un rapido esempio. Supponiamo che tu abbia un database aziendale con una tabella chiamata Employee. La tabella Employee potrebbe avere cinque colonne digitate: EmployeeID (numero), FirstName (stringa), LastName (stringa), Title (stringa) e Stipendio (numero). È quindi possibile aggiungere un record al database per un dipendente di nome John Doe e un record separato per un dipendente di nome Anne Droid.
I dati all'interno di un database devono essere ispezionati e manipolati. I dati all'interno di una tabella possono essere:
INSERIRE
comando)AGGIORNARE
comando)ELIMINA
comando)Puoi cercare dati specifici all'interno di un database usando quella che viene chiamata una query. Una query (utilizzando il comando SELECT) può coinvolgere una tabella o più tabelle. Per creare una query, è necessario specificare le tabelle, le colonne di dati e i valori dei dati di interesse utilizzando il linguaggio dei comandi SQL. Ogni comando SQL è terminato con un punto e virgola (;).
Il modo migliore per capire veramente come funzionano i database SQLite è quello di lavorare con un semplice esempio, quindi facciamolo. Facciamo finta che abbiamo un'applicazione che tiene traccia dei punteggi dei giocatori da un torneo di scacchi casual. I punteggi dei giocatori vengono registrati e quindi, al termine di una serie di partite, viene determinato il vincitore. Il punteggio complessivo del torneo di ogni giocatore viene calcolato in base a:
Nota: per il torneo, i punteggi dei giocatori possono essere basati su una formula che influisce sul tempo impiegato per vincere la partita e sul tipo e numero di pezzi rimasti sul tabellone alla fine del gioco. In questo modo, un giocatore forte riceverà un punteggio elevato per perdere pochi pezzi potenti e vincere il gioco rapidamente. Forse lo stile e l'atteggiamento sono inclusi dai giudici per incoraggiare il gioco divertente e leggero. Il modo in cui i punteggi vengono calcolati non è davvero importante per il modo in cui definiamo il nostro database; li archiviamo nel database. Per semplicità, supponiamo che i punteggi siano basati su una scala da 0 a 100.
Uno schema di database è semplicemente la definizione della struttura del database in termini di tabelle, colonne di dati e così via. Lo schema per il nostro database dei tornei è abbastanza semplice:
Lo schema del database TournamentScores ha tre tabelle:
SQLite3 supporta i seguenti tipi di dati comuni per le colonne:
NUMERO INTERO
(numeri interi firmati)VERO
(valori a virgola mobile)TESTO
(Stringa UTF-8 o UTF-16, codificata utilizzando la codifica del database)BLOB
(pezzo di dati)Dopo aver determinato quali colonne sono necessarie per ogni tabella, sei pronto per creare alcune tabelle all'interno dello schema del database.
Iniziamo creando la tabella Giocatori. Questo tavolo richiede un ID giocatore unico per fare riferimento a ciascun giocatore. Possiamo rendere questa la chiave primaria (per identificare univocamente un record in questa tabella) e impostarne l'attributo autoincrement. Autoincrement significa che ogni volta che viene aggiunto un nuovo record giocatore, il record otterrà un nuovo ID giocatore unico. Vogliamo anche memorizzare il nome e il cognome di ciascun giocatore, non sono ammessi valori nulli.
Qui possiamo usare l'istruzione SQL CREATE TABLE per generare la tabella Giocatori:
CREATE TABLE Giocatori (id INTEGER PRIMARY KEY AUTOINCREMENT, fname TEXT NOT NULL, lname TEXT NOT NULL);
La tabella dei giochi è molto simile. Abbiamo bisogno di un ID di gioco unico per fare riferimento a ciascun gioco. Vogliamo anche un nome descrittivo per ogni gioco e un valore di peso per quanto conta il punteggio del torneo finale del giocatore (in percentuale). Ecco l'istruzione SQL per creare la tabella Giochi:
CREA TABELLA Giochi (id INTEGER PRIMARY KEY AUTOINCREMENT, nome del gioco TEXT, peso REAL DEFAULT .10 CHECK (peso<=1));
Puoi anche eliminare le tabelle usando l'istruzione DROP TABLE. Ad esempio, per eliminare la tabella Giochi, utilizzare il seguente comando SQL:
DROP TABLE Giochi;
Prima di procedere, aggiungiamo alcuni dati a queste tabelle. Per aggiungere un record alla tabella Giocatori, è necessario specificare i nomi delle colonne e i valori in ordine. Ad esempio, la seguente istruzione SQL utilizza il comando INSERT per aggiungere un record per il giocatore di scacchi Bobby Fisher:
INSERIRE nei giocatori (fname, lname) VALORI ('Bobby', 'Fisher');
Mentre ci siamo, aggiungeremo altri due giocatori: Bart Simpson (un giocatore di scacchi molto pietoso) e Garry Kasparov (forse il miglior giocatore di scacchi di sempre). Allo stesso tempo, dobbiamo aggiungere un sacco di record alla tabella Giochi. Per prima cosa aggiungiamo la semifinale, che conta per il 25 percento del punteggio del torneo del giocatore:
INSERIRE in Giochi (gamename, weight) VALUES ('Semi-Final', .25);
Quindi aggiungiamo un paio di riscaldi di riscaldamento, che usano il peso predefinito del 10 percento:
INSERISCI in VALORI GIOCHI (nome giocatore) ('Warm-up Heat 1');
Infine, aggiungiamo un valore finale del 35 percento del punteggio totale del torneo:
INSERIRE in Giochi (gamename, weight) VALUES ('Final', .35);
Come sappiamo che i dati che abbiamo aggiunto sono nella tabella? Bene, è facile. Semplicemente interrogiamo per tutte le righe in una tabella usando un'istruzione SELECT:
SELEZIONA * DA giochi;
Questo restituisce tutti i record nella tabella Giochi:
peso del nome del gioco ----- --------------- ------ 1 Semifinale 0,25 2 Riscaldamento di riscaldamento 1 0,1 3 Riscaldamento di riscaldamento 2 0,1 4 Caldo -up Calore 3 0,1 5 Calore di riscaldamento 4 0,1 6 Finale 0,35
Possiamo anche creare le nostre colonne e renderle analoghe. Ad esempio, possiamo creare un alias di colonna chiamato PlayerName che è una colonna calcolata: è il nome e il cognome del giocatore concatenati usando || operatore, separato da uno spazio:
SELECT fname || "|| lname AS PlayerName, id FROM Players;
Questa query produce i seguenti risultati:
PlayerName id ------------ - Bobby Fisher 1 Bart Simpsen 2 Garry Kasparov 3
Il cognome Bart (id giocatore 2) è scritto in modo errato. Per aggiornare la tabella Giocatori in modo che rifletta l'ortografia corretta, è possibile utilizzare il comando UPDATE:
AGGIORNAMENTO Giocatori SET lname = "Simpson" WHERE playerid = 2;
Puoi eliminare le righe da una tabella usando la funzione DELETE. Ad esempio, per eliminare il record che abbiamo appena aggiornato:
CANCELLA DA giocatori DOVE playerid = 2;
Puoi eliminare tutte le righe in una tabella non specificando la clausola WHERE:
CANCELLA DA Giocatori;
Ora che abbiamo creato tutti i nostri giocatori e giochi, creiamo la tabella GameResults. Questa è una tabella più complicata. La tabella GameResults accoppia gli ID giocatore della tabella Giocatori con gli ID di gioco dalla tabella Giochi e quindi elenca il punteggio che il giocatore ha guadagnato per il gioco specifico. Le colonne, che si collegano ad altre tabelle in questo modo, sono spesso chiamate chiavi esterne. Vogliamo abbinamenti giocatore-gioco unici, quindi creiamo una chiave primaria composta da chiavi esterne giocatore e gioco, per identificare in modo univoco un record GameResults. Infine, applichiamo che i punteggi sono numeri interi tra 0 e 100.
CREATE TABLE GameResults (playerid INTEGER REFERENCES Giocatori (id), gameid INTEGER REFERENCES Giochi (id), segna INTEGER CHECK (punteggio<=100 AND score>= 0), PRIMARY KEY (playerid, gameid));
(Nota: SQLite non impone vincoli di chiave esterna, ma è comunque possibile impostarli e applicare i vincoli creando dei trigger.)
Ora è il momento di inserire alcuni dati nella tabella GameResults. Diciamo che Bobby Fisher (giocatore id 1) ha ricevuto un punteggio di 82 punti in semifinale (gioco ID 1). È possibile utilizzare il seguente comando SQL per inserire il record appropriato nella tabella GameResults:
INSERISCI i valori di GameResults (playerid, gameid, score) (1,1,82);
Ora supponiamo che il torneo venga giocato e che i punteggi vengano aggiunti alla tabella GameResults. Bobby è un buon giocatore, Bart è un giocatore terribile, e Garry gioca sempre un gioco perfetto. Una volta che i record sono stati aggiunti alla tabella GameResults, possiamo eseguire un comando SELECT * per elencare tutti i record nella tabella, oppure possiamo specificare le colonne esplicitamente in questo modo:
SELECT playerid, gameid, score FROM GameResults;
Ecco i risultati di questa query:
score gameid playerid ---------- ---------- ----- 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
Come puoi vedere, questo elenco non è particolarmente "leggibile".
Non sarebbe più utile se i nomi dei giocatori e dei Giochi fossero mostrati al posto dei loro ID numerici? La ricerca e la combinazione dei dati nelle istruzioni SELECT vengono spesso gestite eseguendo un JOIN con più origini tabella; ci sono diversi tipi di JOIN. Quando lavori con più tabelle, devi specificare a quale tabella appartiene una colonna (specialmente quando le colonne sono identificate come con tutte queste colonne id diverse). È possibile fare riferimento alle colonne in base al nome della colonna o al nome della tabella, quindi a un punto (.) E quindi al nome della colonna.
Rimettiamo i punteggi del giocatore di nuovo, solo questa volta, includendo il nome del gioco e il nome del giocatore. Inoltre, limitiamo i nostri risultati solo al punteggio per la finale (id del gioco 6):
SELECT 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;
che ci dà i seguenti risultati (potresti lasciare il WHERE per ottenere tutti i giochi):
PlayerName punteggio del nome del giocatore ------------------ -------------- ----- Bobby Fisher Final 94 Bart Simpson finale 65 Garry Kasparov Finale 100
Il cielo è il limite quando si tratta delle domande che potresti eseguire qui. Per il nostro esempio, la query più importante è quella che ci dice chi ha vinto il torneo.
Ecco la query finale per il calcolo delle classifiche del torneo:
SELECT Players.fname || "|| Players.lname AS PlayerName, SUM ((Games.weight * GameResults.score)) AS TotalWeightedScore DA GameResults UNIONE Giocatori ON (GameResults.playerid = Players.id) JOIN Games ON (GameResults.gameid = Games.id) GROUP BY GameResults.playerid ORDER BY TotalWeightedScore DESC;
Questa query raccoglie informazioni da diverse tabelle utilizzando JOIN e calcola i risultati del torneo in modo leggibile. Diamo un'occhiata a cosa fa questa query:
I risultati di questa query sono mostrati di seguito:
PlayerName TotalWeightedScore ------------------------- ----------------- Garry Kasparov 100.0 Bobby Fisher 87,5 Bart Simpson 46.25
Questo conclude la nostra esplorazione di un semplice esempio di database SQLite: un database di tornei di scacchi. Si spera che tu abbia riacquistato te stesso con concetti di database relazionali come tabelle, record e query e familiarizzato con molti dei comandi SQLite comunemente usati. Infine, hai analizzato il design e l'utilizzo di un database di esempio. Ora che hai un'idea su come funzionano i database SQLite, sei pronto per usarli nelle tue applicazioni Android (il tema del nostro prossimo tutorial in questa serie).
Gli sviluppatori mobili Lauren Darcey e Shane Conder hanno coautore diversi libri sullo sviluppo di Android: un libro di programmazione approfondito intitolato Sviluppo di applicazioni wireless Android e Sams TeachYourself Sviluppo di applicazioni Android in 24 ore. Quando non scrivono, passano il loro tempo a sviluppare software mobile presso la loro azienda ea fornire servizi di consulenza. Possono essere contattati via email a [email protected], tramite il loro blog su androidbook.blogspot.com e su Twitter @androidwireless.