Išmokite Duomenų bazės ir SQL nuo nulio
1Kas yra reliacinė duomenų bazė
Reliacinė duomenų bazė saugo duomenis lentelėse. Lentelė atrodo kaip skaičiuoklė: kiekviena eilutė yra vienas įrašas, kiekvienas stulpelis – viena savybė.
Parduotuvė gali turėti lentelę customers su stulpeliais id, name ir city bei lentelę orders su stulpeliais id, customer_id ir total.
Pirminis raktas yra stulpelis ar stulpelių rinkinys, vienareikšmiškai identifikuojantis kiekvieną eilutę. Jis niekada negali kartotis ir niekada negali būti tuščias. Čia tai kiekvienos lentelės id.
Išorinis raktas yra stulpelis, nurodantis kitos lentelės pirminį raktą. Lentelėje orders customer_id nurodo, kuris klientas pateikė užsakymą.
Taip lentelės susiejamos: vienas klientas gali turėti daug užsakymų, bet kiekvienas užsakymas priklauso vienam klientui. Tai vienas su daug ryšys.
SQL (Structured Query Language) yra kalba, kuria kuriate lenteles, keičiate duomenis ir klausiate apie juos.
Savikontrolė Kas yra pirminis raktas?
- Indeksas, pagreitinantis paiešką
- Pirmasis kiekvienos lentelės stulpelis
- Stulpelis ar stulpelių rinkinys, vienareikšmiškai identifikuojantis kiekvieną eilutę
- Stulpelis, nurodantis eilutę kitoje lentelėje
Atsakymas: Stulpelis ar stulpelių rinkinys, vienareikšmiškai identifikuojantis kiekvieną eilutę. Pirminis raktas yra unikalus ir niekada nėra NULL, todėl išrenka lygiai vieną eilutę. Stulpelis, nurodantis kitą lentelę, yra išorinis raktas.
2Duomenų skaitymas su SELECT
Dauguma klausimų yra apie SELECT sakinį. Jis sudarytas iš sakinių dalių, visada rašomų šia tvarka:
SELECT … FROM … WHERE … GROUP BY … HAVING … ORDER BY …
- SELECT išvardija norimus stulpelius. DISTINCT pašalina pasikartojančias eilutes.
- FROM nurodo lentelę arba kartu sujungtas lenteles.
- WHERE palieka tik eilutes, atitinkančias sąlygą, pavyzdžiui, WHERE total > 20.
- GROUP BY sudeda tą pačią reikšmę turinčias eilutes į vieną grupę, kad galėtumėte skaičiuoti ar sumuoti pagal grupę.
- HAVING palieka tik grupes, atitinkančias sąlygą. Jis gali naudoti agregatus, o WHERE – ne.
- ORDER BY rūšiuoja rezultatą, pagal numatymą didėjimo tvarka; pridėkite DESC, kad didžiausi būtų pirmi.
Agregatinės funkcijos apibendrina daug eilučių į vieną reikšmę: COUNT, SUM, AVG, MIN ir MAX.
Duomenų bazė sakinio dalių nevykdo ta tvarka, kuria jas rašote. Ji pirmiausia vykdo FROM, tada WHERE, GROUP BY, HAVING, SELECT ir galiausiai ORDER BY.
Kiti sakiniai keičia duomenis: INSERT prideda eilutes, UPDATE keičia eilutes, o DELETE pašalina eilutes. CREATE, ALTER ir DROP keičia pačias lenteles.
Savikontrolė Norite tik klientų, turinčių daugiau nei 5 užsakymus. Kuri dalis filtruoja pagal COUNT(*) > 5?
- DISTINCT
- HAVING
- ORDER BY
- WHERE
Atsakymas: HAVING. Skaičius egzistuoja tik sugrupavus eilutes, o HAVING filtruoja grupes. WHERE vykdomas prieš grupavimą, todėl negali naudoti agregato, tokio kaip COUNT.
3Sujungimai, normalizavimas ir transakcijos
Sujungimas (join) sujungia dviejų lentelių eilutes pagal sąlygą, paprastai išorinis raktas = pirminis raktas:
FROM customers c JOIN orders o ON o.customer_id = c.id
- INNER JOIN (arba JOIN) palieka tik eilutes, turinčias atitikmenį abiejose lentelėse.
- LEFT JOIN palieka kiekvieną kairiosios lentelės eilutę. Kur atitikmens nėra, dešiniosios lentelės stulpeliai yra NULL.
- NULL reiškia, kad reikšmės nėra arba ji nežinoma. Tikrinkite su IS NULL, niekada su = NULL.
Normalizavimas suskaido lenteles, kad kiekvienas faktas būtų saugomas vieną kartą. Taip išvengiama to paties fakto atnaujinimo keliose vietose.
- 1NF: kiekvienas langelis turi vieną atominę reikšmę, be pasikartojančių grupių.
- 2NF: 1NF, ir kiekvienas ne rakto stulpelis priklauso nuo viso rakto, o ne nuo sudėtinio rakto dalies.
- 3NF: 2NF, ir joks ne rakto stulpelis nepriklauso nuo kito ne rakto stulpelio.
Transakcija sugrupuoja sakinius į vieną vienetą. COMMIT padaro ją nuolatinę, o ROLLBACK ją atšaukia. Transakcijos laikosi ACID: atomiškumas (viskas arba nieko), nuoseklumas, izoliuotumas ir patvarumas.
Savikontrolė Klientas nepateikė jokių užsakymų. Kas nutinka tam klientui užklausoje customers LEFT JOIN orders?
- Klientas pasirodo kiekvieną kartą už kiekvieną lentelės užsakymą
- Klientas pasirodo vieną kartą, su NULL užsakymų stulpeliuose
- Klientas praleidžiamas rezultate
- Užklausa nepavyksta ir grąžina klaidą
Atsakymas: Klientas pasirodo vieną kartą, su NULL užsakymų stulpeliuose. LEFT JOIN palieka kiekvieną kairiosios lentelės eilutę ir trūkstamą dešinę pusę užpildo NULL. Kliento praleidimas yra tai, ką daro INNER JOIN.
4Metodas žingsnis po žingsnio
Norėdami parašyti užklausą arba išsiaiškinti, ką grąžina duota užklausa:
- Raskite lenteles, kuriose saugomi duomenys, ir kaip jos susietos raktais.
- Parašykite FROM su sujungimais. Rinkitės LEFT JOIN, kai eilutės be atitikmens turi likti.
- Pridėkite WHERE sąlygoms atskiroms eilutėms.
- Jei klausime yra „kiekvienam“ ar „pagal“, pridėkite GROUP BY ir agregatą.
- Pridėkite HAVING agregato sąlygoms, tada ORDER BY, jei svarbi tvarka.
- Patikrinkite rezultatą nedideliame pavyzdyje: išvardykite eilutes po kiekvienos sakinio dalies tokia tvarka, kokia jas vykdo duomenų bazė.
Teorijos klausimui pirmiausia įvardykite sąvoką (raktas, sujungimo tipas, normalinė forma, ACID savybė), tada pasirinkite variantą, atitinkantį jos apibrėžimą.
5Išspręstas pavyzdys
Sekite kiekvieną žingsnį. Pabandykite nuspėti kitą, prieš jį atidarydami.
Išspręstas pavyzdysLentelėje customers yra eilutės (1, Ana), (2, Ben) ir (3, Cas). Lentelėje orders yra eilutės (id, customer_id) = (10, 1), (11, 1), (12, 2) ir (13, 1). Ką grąžina ši užklausa? SELECT c.name, COUNT(o.id) FROM customers c LEFT JOIN orders o ON o.customer_id = c.id GROUP BY c.name
1Kiekvienas klientas suporuojamas su užsakymais, turinčiais jo id. Ana atitinka užsakymus 10, 11 ir 13. Benas atitinka užsakymą 12.
Cas užsakymų neturi. Kadangi tai LEFT JOIN, Cas lieka rezultate, o o.id yra NULL.
2- Ana, 10
- Ana, 11
- Ana, 13
- Ben, 12
- Cas, NULL
Tai 5 eilutės.
3GROUP BY c.name sudaro tris grupes: Ana su 3 eilutėmis, Ben su 1 eilute ir Cas su 1 eilute.
4COUNT(o.id) skaičiuoja tik reikšmes, kurios nėra NULL. Ana gauna 3, o Ben gauna 1.
Cas turi vieną eilutę, bet jo o.id yra NULL, todėl Cas gauna 0.
5Ana, Ben ir Cas kartu turi 3 + 1 + 0 = 4 užsakymus, tiek pat, kiek eilučių lentelėje orders. Su COUNT(*) vietoj to Cas klaidingai gautų 1, nes COUNT(*) skaičiuoja pačią eilutę.
Atsakymas Ana 3, Ben 1, Cas 0.
6Dažnos klaidos
- Agregatas naudojamas WHERE. COUNT, SUM ar AVG sąlygos priklauso HAVING.
- Rašoma = NULL. Bet koks palyginimas su NULL yra nežinomas; naudokite IS NULL arba IS NOT NULL.
- Naudojamas INNER JOIN, kai eilutės be atitikmens turi likti. Naudokite LEFT JOIN.
- Pamirštama sujungimo sąlyga. Be ON kiekviena eilutė suporuojama su kiekviena eilute (kryžminis sujungimas).
- Parenkamas stulpelis, kurio nėra nei GROUP BY, nei agregate.
- Painiojami DELETE (pašalina eilutes) ir DROP TABLE (pašalina visą lentelę).
- UPDATE arba DELETE vykdomas be WHERE. Jis pakeičia kiekvieną lentelės eilutę.
Savikontrolė Lentelė turi 10 eilučių, o stulpelis col yra NULL kiekvienoje eilutėje. Ką grąžina SELECT COUNT(col)?
- 0
- 10
- 1
- NULL
Atsakymas: 0. COUNT(col) skaičiuoja tik reikšmes, kurios nėra NULL, todėl grąžina 0. COUNT(*) skaičiuoja eilutes ir grąžintų 10.
7Kaip atrodo egzamino uždaviniai
- Lengvi: pagrindinės sąvokos ir faktai. Ką daro SELECT, WHERE, ORDER BY ar DELETE, pirminiai ir išoriniai raktai, ką reiškia NULL.
- Vidutiniai: sąvokų taikymas. Tinkama užklausa užduočiai, WHERE ir HAVING skirtumas, vidiniai ir išoriniai sujungimai, normalinės formos, ACID.
- Sunkūs: atvejai ir analizė. Vidinės užklausos, izoliacijos lygiai ir jų anomalijos, BCNF, langų funkcijos, indeksai ir užklausų našumas, SQL injekcija.
Kai duota užklausa, atsekite ją keliose eilutėse tokia tvarka: FROM, WHERE, GROUP BY, HAVING, SELECT, ORDER BY. Dauguma spąstų paaiškėja per tris eilutes.
Mokykitės žingsnis po žingsnio programėlėjeMokykitės žingsnis po žingsnio programėlėje