SQLite Crash Course pentru dezvoltatorii Android

Aplicațiile Android pot memora datele aplicațiilor în bazele de date SQLite. În acest tutorial, veți afla cum sunt proiectate și manipulate bazele de date SQLite.

Aici începem prin proiectarea și utilizarea unei baze de date simple SQLite pentru a gestiona scorurile din turneele de șah. Acest tutorial este conceput ca o scurtă trecere în revistă a modului în care funcționează bazele de date SQLite. Aceste cunoștințe vor fi apoi folosite în tutoriale de dezvoltare viitoare pentru implementarea aplicațiilor Android bazate pe baze de date.

Noțiuni de bază

Aplicațiile Android pot crea și manipula propriile baze de date relaționale private SQLite. De asemenea, dezvoltatorii pot inspecta și modifica bazele de date pe un emulator sau pe un dispozitiv Android folosind instrumentul de comandă sqlite3 furnizat ca parte a instrumentului Android SDK numit Bridge Debug Bridge (Adb).

În acest tutorial, presupunem că aveți o înțelegere a bazelor de date relaționale, în teorie, dar necesită un pic de curs de perfecționare înainte de a le utiliza în aplicațiile Android. Acest tutorial nu necesită niciun fel de instrumente; este mai mult un exercițiu teoretic.

Cu toate acestea, dacă intenționați să dezvoltați aplicații Android care se bazează pe bazele de date SQLite, va trebui să instalați instrumentele necesare dezvoltării Android, cum ar fi SDK-ul Android și Eclipse IDE. Consultați multe alte tutoriale Android disponibile aici pe Mobiletuts + pentru a vă ajuta să lucrați cu aceste sarcini.

Ce este SQLite?

SQLite este un motor baze de date relaționale ușoare. SQLite este rapid și are o amprentă redusă, ceea ce îl face perfect pentru dispozitivele Android. În locul bazelor de date bazate pe servere, cum ar fi Oracle și Microsoft SQL Server, fiecare bază de date SQLite este stocată într-un singur fișier pe disc. Aplicațiile Android pot alege să stocheze datele de aplicație privată într-o bază de date SQLite.

Notă: Dacă sunteți familiarizat cu SQL, atunci SQLite va fi foarte ușor de preluat. SQLite este practic un motor baze de date SQL dezinfectat pentru dispozitivele încorporate. Pentru informații specifice despre SQLite și despre caracteristicile, funcționalitatea și limitările acestuia, consultați documentația online SQLite.

O revizuire rapidă a bazelor de date ale bazei de date

O bază de date este pur și simplu o metodă structurată de stocare a datelor în mod persistent. Datele sunt stocate în tabele. Un tabel are coloane cu diferite tipuri de date. Fiecare rând dintr-un tabel reprezintă o înregistrare de date. S-ar putea să fiți de ajutor să vă gândiți la o masă ca o foaie de calcul Excel. Pentru o perspectivă de programare orientată obiect, fiecare tabel dintr-o bază de date reprezintă adesea un obiect (reprezentat de o clasă). Fiecare coloană de tabel reprezintă un atribut de clasă. Fiecare înregistrare dintr-un tabel reprezintă o instanță specifică a obiectului respectiv.

Să examinăm un exemplu rapid. Să presupunem că aveți o bază de date a companiei cu un tabel numit Angajat. Tabelul Angajat ar putea avea cinci coloane tipizate: Numar angajat (numar), FirstName (string), LastName (string), Titlu (sir) si Salariu (numar). Apoi, puteți adăuga o înregistrare la baza de date pentru un angajat numit John Doe și o înregistrare separată pentru un angajat numit Anne Droid.

Datele dintr-o bază de date sunt menite să fie inspectate și manipulate. Datele dintr-un tabel pot fi:

  • Adăugat (folosind INTRODUCE comanda)
  • Modificat (folosind ACTUALIZAȚI comanda)
  • Eliminat (folosind ȘTERGE comanda)

Puteți căuta date specifice dintr-o bază de date utilizând ceea ce se numește interogare. O interogare (folosind comanda SELECT) poate implica un tabel sau mai multe tabele. Pentru a crea o interogare, trebuie să specificați tabelele, coloanele de date și valorile de date de interes folosind limbajul de comandă SQL. Fiecare comandă SQL este terminată cu un punct și virgulă (;).

Baza de date a turneelor ​​de șah

Cea mai bună modalitate de a înțelege cu adevărat modul în care funcționează bazele de date SQLite este să lucrezi printr-un exemplu simplu, deci hai să facem acest lucru. Să presupunem că avem o aplicație care ține evidența scorurilor jucătorilor dintr-un turneu ocazional de șah. Scorurile jucătorului sunt înregistrate și apoi, la sfârșitul unei serii de meciuri, câștigătorul este determinat. Scorul general al turneului jucătorului este calculat pe baza performanței sale la:

  • Patru încălzitoare de încălzire (greutate: 10% din scorul total fiecare)
  • Un semifinale (greutate: 25% din scorul total)
  • Un final (greutate: 35% din scorul global)

Notă: pentru turneu, scorurile jucătorilor ar putea fi bazate pe o formulă care influențează timpul necesar pentru a câștiga jocul și tipul și numărul de piese rămase pe tablă la sfârșitul jocului. În acest fel, un jucător puternic va primi un scor mare pentru că a pierdut câteva piese puternice și a câștigat rapid jocul. Poate că stilul și atitudinea sunt incluse de către judecători pentru a încuraja distracția, jocul ușor. Cum se calculează scorurile nu este cu adevărat importantă pentru modul în care definim baza noastră de date; le stocăm doar în baza de date. Pentru simplitate, vom presupune că scorurile se bazează pe o scară de la 0 la 100.

Proiectarea schemei de baze de date

O schemă de bază de date este pur și simplu definirea structurii bazei de date în ceea ce privește tabelele, coloanele de date și altele asemenea. Schema pentru baza de date a turneelor ​​noastre este destul de simplă:

Schema bazei de date TournamentScores are trei tabele:

  • Tabelul Jucători conține informații despre jucător.
  • Tabela de jocuri conține informații despre fiecare joc și cât de mult contează pentru scorul general al turneului jucătorului.
  • Tabelul GameResults conține scorurile tuturor jucătorilor.

SQLite3 are suport pentru următoarele tipuri de date comune pentru coloane:

  • ÎNTREG (numere întregi)
  • REAL (valori în virgulă mobilă)
  • TEXT (Șir UTF-8 sau UTF-16, codificat folosind codificarea bazei de date)
  • BLOB (bucată de date)

Odată ce ați determinat care coloane sunt necesare pentru fiecare tabel, sunteți gata să creați câteva tabele în schema bazei de date.

Lucrul cu tabelele

Să începem prin crearea tabelului Jucători. Acest tabel necesită un id de jucător unic pentru a face referire la fiecare jucător. Putem face cheia primară (pentru a identifica în mod unic o înregistrare în acest tabel) și a seta atributul autoincrement. Autoincrement înseamnă că de fiecare dată când este adăugat un nou record de jucător, înregistrarea va primi un nou ID de jucător unic. De asemenea, dorim să stocăm numele și prenumele fiecărui jucător - nu sunt permise nuluri.
Aici putem folosi instrucțiunea CREATE TABLE SQL pentru a genera tabela Players:

CREAȚI TABELUL Jucătorilor (id INTEGER AUTOINCREMENT KEY PRIMARY, fname TEXT NOT NULL, lname TEXT NOT NULL); 

Tabela de jocuri este foarte asemănătoare. Avem nevoie de un id de joc unic pentru a face referire la fiecare joc. De asemenea, dorim un nume prietenos pentru fiecare joc și o valoare a greutății pentru cât de mult jocul contează pentru scorul final al turneului jucătorului (în procente). Iată instrucțiunea SQL pentru a crea tabelul Jocuri:

CREATE TABLE Jocuri (id INTEGER PRIMARY KEY AUTOINCREMENT, gamename TEXT, greutate REAL DEFAULT .10 CHECK (greutate<=1)); 

De asemenea, puteți șterge tabele utilizând instrucțiunea DROP TABLE. De exemplu, pentru a șterge tabelul Jocuri, utilizați următoarea comandă SQL:

DROP TABLE Jocuri; 

Populația tabelelor cu înregistrări de date

Înainte de a merge mai departe, să adăugăm câteva date în aceste tabele. Pentru a adăuga o înregistrare în tabela Jucători, trebuie să specificați numele și numele valorilor în ordine. De exemplu, următoarea instrucțiune SQL folosește comanda INSERT pentru a adăuga o înregistrare pentru jucătorul de șah Bobby Fisher:

INSCRIȚI în Jucători (fname, lname) VALUES ("Bobby", "Fisher"); 

În timp ce ne aflăm, vom adăuga încă doi jucători: Bart Simpson (un jucător de șah foarte jalnic) și Garry Kasparov (probabil cel mai bun jucător de șah vreodată). În același timp, trebuie să adăugăm o grămadă de înregistrări la masa jocurilor. Mai întâi adăugăm semifinala, care reprezintă 25% din scorul jucat de turneu:

INSCRIȚI în Jocuri (gamename, greutate) VALORI ("Semi-Final", .25); 

Apoi adăugăm un cuplu de încălzire încălzită, care utilizează greutatea prestabilită de 10 la sută:

INSCRIȚI în Jocuri (gamename) VALUES ("Căldură încălzită 1"); 

În final, adăugăm o valoare finală de 35% din scorul total al turneului:

INSCRIEȚI în Jocuri (gamename, greutate) VALUES ("Final", .35); 

Solicitarea de tabele pentru rezultate cu SELECT

Cum știm că datele pe care le-am adăugat sunt în tabel? Ei bine, este ușor. Pur și simplu căutăm pentru toate rândurile dintr-un tabel folosind o instrucțiune SELECT:

SELECT * FROM Jocuri; 

Aceasta returnează toate înregistrările din tabelul Jocuri:

id gamename greutate ----- --------------- ------ 1 Semifinale 0.25 2 Căldură de încălzire 1 0.1 3 Căldură de încălzire 2 0.1 4 Caldă -căldură 3 0,1 5 încălzire încălzită 4 0,1 6 finală 0,35 

Utilizarea aliaselor de coloane și a coloanelor calculate

De asemenea, putem crea propriile coloane și le putem alias. De exemplu, putem crea un alias de coloană numit PlayerName care este o coloană calculată: Numele și numele ultimului jucător sunt concatenate folosind || operator, separat de un spațiu:

SELECT fname || "|| lname AS NumePlayer, id FROM Jucători; 

Această interogare produce următoarele rezultate:

Nume jucător ------------ - Bobby Fisher 1 Bart Simpsen 2 Garry Kasparov 3 

Modificarea datelor din tabele

Numele de familie al lui Bart (id-ul jucătorului 2) este scris în mod incorect. Pentru a actualiza tabelul Jucători pentru a reflecta ortografia corectă, puteți utiliza comanda UPDATE:

UPDATE Jucători SET lname = "Simpson" WHERE playerid = 2; 

Puteți șterge rânduri dintr-o masă utilizând funcția DELETE. De exemplu, pentru a șterge înregistrarea pe care tocmai am actualizat-o:

DELETE FROM Jucători WHERE playerid = 2; 

Puteți șterge toate rândurile într-un tabel, fără a specifica clauza WHERE:

DELETE FROM Jucători; 

Utilizarea cheilor externe și a tastelor compuse

Acum, când avem toți jucătorii și jocurile noastre, să creăm tabelul GameResults. Aceasta este o masă mai complicată. Tabelul GameResults împerechează ID-uri de jucători din tabelul Jucători cu ID-uri de joc din tabelul Jocuri și apoi afișează scorul câștigat de jucător pentru jocul respectiv. Coloanele, care fac legătura cu alte mese în acest fel, sunt deseori numite chei externe. Vrem o pereche de jocuri-joc unice, astfel încât să creați o cheie primară compusă din cheia de player și jocul extern, pentru a identifica în mod unic o înregistrare GameResults. În cele din urmă, punem în aplicare că scorurile sunt numere între 0 și 100.

CREATE TABLE GameResults (playerid INTEGER REFERINȚE Jucători (id), gameid INTEGER REFERINȚE Jocuri (id), scor INTEGER CHECK (scor<=100 AND score>= 0), KEY PRIMARY (playerid, gameid)); 

(Notă: SQLite nu aplică restricții cheie străine, dar le puteți seta oricum și impune constrângerile prin crearea de declanșatoare.)
Acum este momentul să introduceți câteva date în tabela GameResults. Să presupunem că Bobby Fisher (ID-ul jucătorului 1) a primit un scor de 82 de puncte pe semifinala (joc id 1). Ați putea folosi următoarea comandă SQL pentru a insera înregistrarea corespunzătoare în tabelul GameResults:

INSCRIEȚI în GameResults (playerid, gameid, score) VALORI (1,1,82); 

Acum să presupunem că turneul este jucat și scorurile sunt adăugate la tabela GameResults. Bobby este un jucător bun, Bart este un jucător teribil, iar Garry joacă întotdeauna un joc perfect. După ce înregistrările au fost adăugate în tabela GameResults, putem efectua o comandă SELECT * pentru a afișa toate înregistrările din tabel sau putem specifica coloanele în mod explicit astfel:

SELECT jucator, gameid, scor FROM GameResults; 

Iată rezultatele de la această interogare:

Jucătorii scor gameid ---------- ---------- ----- 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 

După cum puteți vedea, această listă nu este deosebit de "citită de om".

Interogarea în mai multe tabele folosind JOIN

Nu ar fi mai util dacă numele jucătorilor și al Jocurilor ar fi afișate în locul numerelor lor numerice? Interogarea și combinarea datelor în instrucțiunile SELECT este adesea rezolvată prin efectuarea unui JOIN cu mai multe surse de tabel; există diferite tipuri de JOINS. Când lucrați cu mai multe tabele, trebuie să specificați tabelul în care aparține o coloană (mai ales atunci când coloanele sunt numite aceleași, cum ar fi cu toate aceste coloane id diferite). Puteți să consultați coloanele după numele coloanelor sau după numele tabelului, apoi un punct (.) Și apoi numele coloanei.

Să relantim scorurile jucătorului din nou, numai de această dată, să includem numele jocului și numele jucătorului. De asemenea, ne limităm rezultatele numai la scorul final (ID-ul jocului 6):

SELECT Players.fname || "|| Jucători.info AS PlayerName, Games.gameame, GameResults.score FROM GameResults Jucători JOIN ON (JocuriResults.playerid = Players.id) Jocuri JOIN ON (GameResults.gameid = Games.id) WHERE gameid = 6; 

care ne dă următoarele rezultate (ați putea lăsa pe WHERE pentru a obține toate jocurile):

Numele jucătorului gamename scor ------------------ -------------- ----- Bobby Fisher Final 94 Bart Simpson Final 65 Garry Kasparov Final 100 

Executarea unor interogări complexe

Cerul este limita când vine vorba de întrebările pe care le puteți efectua aici. Pentru exemplul nostru, cea mai importantă interogare este cea care ne spune cine a câștigat turneul.
Iată întrebarea finală pentru calcularea clasamentelor turneului:

SELECT Play.fname || "|| Players.lname AS Nume jucător, SUM ((Jocuri.weight * GameResults.score)) AS TotalWeightedScore FROM GameResults Jucători JOIN ON (GameResults.playerid = Players.id) JOIN Games ON (GameResults.gameid = Games.id) GRUPUL BY GameResults.playerid ORDER BY TotalWeightedScore DESC; 

Această interogare adună informații din mai multe tabele diferite folosind JOIN și calculează rezultatele turneului într-un mod lizibil. Deci, haideți să ne uităm la ce face această interogare:

  • Numele complet al fiecărui jucător este afișat ca prima coloană a rezultatului (calculată din numele și prenumele)
  • Scorul de turnee al fiecărui jucător este afișat drept coloana a doua (calculată din scorurile ponderate ale tuturor jocurilor jucate de un anumit jucător)
  • Rezultatele înregistrate sunt afișate în ordine descrescătoare pe baza scorurilor la turneu (locul întâi, al doilea loc etc.)

Rezultatele din această interogare sunt prezentate mai jos:

Numele jucătorului TotalWeightedScore ------------------------- ----------------- Garry Kasparov 100.0 Bobby Fisher 87.5 Bart Simpson 46.25 

Concluzie

Aceasta incheie explorarea unui exemplu simplu de baze de date SQLite: o baza de date a turneelor ​​de sah. Sperăm că v-ați recâștigat cu concepte de baze de date relaționale, cum ar fi tabele, înregistrări și interogări și v-ați familiarizat cu multe dintre comenzile SQLite utilizate în mod obișnuit. În cele din urmă, ați trecut prin proiectarea și utilizarea unei baze de date exemplu. Acum, când aveți o manevră asupra modului în care funcționează bazele de date SQLite, sunteți gata să le utilizați în cadrul aplicațiilor Android (subiectul următorului tutorial din această serie).

despre autori

Dezvoltatorii mobili Lauren Darcey și Shane Conder au coautorizat mai multe cărți despre dezvoltarea Android: o carte de programare în profunzime intitulată Dezvoltarea aplicațiilor fără fir Android și Sams TeachYourself Dezvoltarea de aplicații Android în 24 de ore. Când nu scriu, își petrec timpul dezvoltând software-ul mobil la compania lor și oferind servicii de consultanță. Acestea pot fi obținute prin e-mail la androidwirelessdev@[email protected], prin intermediul blogului lor la androidbook.blogspot.com, și pe Twitter @ androidwireless.

Cod