Andmebaasi algus: SQLite ja Python
Loogika
SQLite on hea esimene andmebaas, sest ta ei vaja eraldi serverit ja elab lihtsalt failina.
See teeb ta heaks sillaks nende teemade vahel:
- failid ja failisüsteem
- SQL päringud
- relatsiooniline andmemudel
- Pythoni programm, mis andmebaasi kasutab
Oluline mõte on:
CSVfail on lihtsalt tekstifail- andmebaas lisab sellele struktuuri, päringud ja seosed
Relatsioonilise mõtteviisi kõige tähtsamad algmõisted on:
- tabel: ühe teema andmed
- rida: üks kirje
- veerg: ühe omaduse koht
- primaarvõti: rea unikaalne tunnus
- võõrvõti: viide teise tabeli reale
JOIN: kahe tabeli kokku sidumine seose järgi
SQLite on hea, sest need mõisted saab läbi proovida ilma, et peaksid kohe serverit või pilvekeskkonda haldama.
Kiirülevaade
Eesmärk on liikuda tekstifailidest andmebaasi mõtlemisse ilma eraldi serverit haldamata.
| Käsk või mõiste | Milleks | Mida tavaliselt näed |
|---|---|---|
sqlite3 andmed.db | ava või loo andmebaasifail | interaktiivne SQLite'i käsurida |
.tables | näita tabeleid | tabelite loend |
SQL SELECT | loe ridu | tulemuste tabel või loend |
SQL INSERT | lisa ridu | edukal juhul sageli vaikne |
Pythoni sqlite3 | kasuta sama andmebaasi programmist | päringu tulemus Pythoni objektidena |
Tüüpilised algaja vead
- aetakse segi andmebaasifail ja selles olevad tabelid
- proovitakse
JOIN-i enne, kui tabelite seos on iseenda jaoks selge - unustatakse, et SQL-i tulemused on päringud andmete peal, mitte “faili uus sisu”
Kiirspikker
sqlite3 andmed.dbava andmebaas.tablesnäita tabeleid.schemanäita tabelite struktuuriselect * from tabel limit 5;kuva paar esimest ridaselect ... from a join b on ...;ühenda kaks tabelitselect city, count(*) from students group by city;koonda read rühmade kaupa
Väga praktilised 1-linerid on:
sqlite3 andmed.db '.tables'
sqlite3 andmed.db '.schema'
sqlite3 andmed.db 'select * from students limit 5;'
sqlite3 andmed.db 'select s.name, r.score from results r join students s on s.id = r.student_id;'
sqlite3 andmed.db 'select city, count(*) from students group by city order by count(*) desc;'
Need on head just sellepärast, et ei pea alati minema interaktiivsesse sqlite3 shelli, kui tahad lihtsalt kiiret vastust.
Kõige tavalisemad käsukujud
create table ...;loo tabelinsert into ... values (...);lisa readselect * from ...;kuva kõik readselect ... from ... where ...;filtreeriselect ... from a join b on ...;ühenda tabelidselect ..., count(*) from ... group by ...;loenda rühmade kaupa
Hea rusikareegel:
- üks tabel kirjeldab üht tüüpi asja
- teise tabeli viide esimesele tabelile tehakse võõrvõtmega
JOINei ole eraldi maagia, vaid viis need read omavahel kokku viia
Näited
Näide: üks tabel
Loome väga väikese andmebaasi ühe tabeliga:
sqlite3 andmed.db <<'EOF'
drop table if exists students;
create table students (
id integer primary key,
name text not null,
city text,
score integer
);
insert into students (name, city, score) values
('Mari', 'Tartu', 91),
('Jaan', 'Tallinn', 84),
('Liis', 'Narva', 88);
select * from students;
EOF
Siin:
id integer primary keyannab igale reale unikaalse tunnusename,cityjascoreon veerud- iga
insertlisab ridu
Kasulikud järgmised vaated:
sqlite3 andmed.db '.schema students'
sqlite3 andmed.db 'select name, score from students order by score desc;'
sqlite3 andmed.db 'select city, count(*) from students group by city;'
Näide: kaks tabelit ja JOIN
Nüüd teeme andmemudeli natuke realistlikumaks. Punktid ei pea olema samas tabelis nagu tudengi põhiandmed.
sqlite3 andmed.db <<'EOF'
drop table if exists results;
drop table if exists students;
create table students (
id integer primary key,
name text not null,
city text
);
create table results (
id integer primary key,
student_id integer not null,
subject text not null,
score integer not null,
foreign key (student_id) references students(id)
);
insert into students (id, name, city) values
(1, 'Mari', 'Tartu'),
(2, 'Jaan', 'Tallinn'),
(3, 'Liis', 'Narva');
insert into results (student_id, subject, score) values
(1, 'matemaatika', 91),
(1, 'python', 95),
(2, 'matemaatika', 84),
(2, 'python', 79),
(3, 'matemaatika', 88),
(3, 'python', 90);
EOF
Nüüd:
- tabel
studentshoiab tudengite põhiandmeid - tabel
resultshoiab tulemusi results.student_idviitabstudents.idväljale
See ongi relatsioonilise andmemudeli põhiidee: seosed tehakse võtmete kaudu, mitte suvalise tekstilise kokkusobitamisega.
Vaatame tulemusi:
sqlite3 andmed.db 'select * from students;'
sqlite3 andmed.db 'select * from results;'
Ja nüüd ühendame need:
sqlite3 andmed.db "
select s.name, s.city, r.subject, r.score
from results r
join students s on s.id = r.student_id
order by s.name, r.subject;
"
Siin:
rjason lühikesed aliased tabelinimedelejoin students s on s.id = r.student_idütleb, kuidas read kokku viiakse- väljundis näed ühe tabeli asemel kahe tabeli kombineeritud pilti
Näide: GROUP BY
Sageli ei taheta näha kõiki ridu, vaid kokkuvõtet.
Näiteks tudengite keskmine tulemus:
sqlite3 andmed.db "
select s.name, round(avg(r.score), 1) as avg_score
from results r
join students s on s.id = r.student_id
group by s.id, s.name
order by avg_score desc;
"
Ja näiteks linnade kaupa tudengite arv:
sqlite3 andmed.db "
select city, count(*) as students_in_city
from students
group by city
order by students_in_city desc, city;
"
See on oluline vahe:
JOINtoob seotud read kokkuGROUP BYteeb neist koondvaate
Näide Pythoniga
SQLite ja Python sobivad hästi kokku, sest Pythonis on sqlite3 moodul kohe olemas.
import sqlite3
conn = sqlite3.connect("andmed.db")
cur = conn.cursor()
cur.execute("""
select s.name, round(avg(r.score), 1) as avg_score
from results r
join students s on s.id = r.student_id
group by s.id, s.name
order by avg_score desc
""")
for name, avg_score in cur.fetchall():
print(f"{name}: {avg_score}")
conn.close()
Siin:
- Python ei asenda SQL-i, vaid kasutab seda
- SQL teeb andmete valiku ja koondamise
- Python saab tulemuse kätte ja teeb sellega edasi, mida vaja
Hea tööjaotus on sageli just selline:
- SQL: vali, ühenda, koonda
- Python: töötle, teisenda, visualiseeri, ehita suurem programm
Minitest
- Loo tabel
students, kus on vähemalt väljadid,namejacity. - Loo teine tabel, mis viitab tudengi
idväärtusele võõrvõtmega. - Tee päring, mis kasutab
JOIN-i, et kuvada mõlema tabeli info koos. - Tee päring, mis kasutab
GROUP BY-d, et anda väike kokkuvõte. - Selgita ühe lausega, miks
CSVfail ja andmebaasitabel ei ole sama asi.
Lisalugemine
Selle teema usaldusväärsemad viited leiad lisast Lisa E: usaldusväärsed viited ja lisalugemine.
Peatüki täisspikker
Edasijõudnu
Eesmärk
SQLite on sild tekstifailide ja päris andmebaasimõtte vahel: failina lihtne, SQL-i mõttes siiski relatsiooniline andmebaas.
Põhikujud
sqlite3 andmed.dbava või loo failsqlite3 andmed.db '.tables'vaata tabeleidsqlite3 andmed.db '.schema'vaata struktuurisqlite3 andmed.db 'select * from students limit 5;'piilu ridusqlite3 andmed.db 'select city, count(*) from students group by city;'koonda readsqlite3 andmed.db 'select s.name, r.score from results r join students s on s.id = r.student_id;'ühenda tabelidpython3 naide.pykasuta Pythonist
Olulised mõisted
primary keyrea unikaalne idforeign keyviide teise tabelisseJOINseo tabelidGROUP BYkoonda read